Secondary Effects

Creating a new Secondary Effect.

1. In the document secondaryEffects.cs, create a new function with naming convention [new name]Effect(%attacker, %attackingObject, %defender). Do all one time calculations here. If the secondary effect should be applied for an extended duration then also create a status effect, described in step 2.

Example of a one time effect:

function pushEffect(%attacker, %attackingObject, %defender)
{
	%blocked = getWord(checkForObstacles(%defender, %attacker.directionX, %attacker.directionY, %attacker.class), 0);
	if(!%blocked)
	{
		%defender.setPosition(%defender.getPositionX() + %attacker.directionX * $globalFloorTileSize, %defender.getPositionY() + %attacker.directionY * $globalFloorTileSize);
	}
}

Example of an ongoing effect:

function slimeEffect(%attacker, %attackingObject, %defender)
{
	%defender.movementCostBonusMonster = %attackingObject.value;
	%statusEffect = createStatusEffect(%attackingObject.type, %attackingObject.duration, %attackingObject.value, 0, false, %defender, "movementCostBonusMonster");
	%statusEffect.setTimerOn(1000);
	%defender.statusEffects = %defender.statusEffects SPC %statusEffect;
	%defender.statusEffects = trim(%defender.statusEffects);
}

2. In the document secondaryEffects.cs in the function createMonsterSecondaryEffect(%effect) you add the new effect as a scriptObject. The scriptObject needs the fields: duration, value, type, effect. duration is the time in seconds, value is an absolute value, type is the type of effect and effect is the function name used. The %effect argument that the function is asking for is just an arbitrary name of the effect. A good rule is to keep it as simple as possible. If the names are kept as one word without spaces they can easily be added to a list which can be used to assign random secondary effects to items.

Assigning a Secondary Effect to an item.

1. Assign the secondary effects function name as a string in %weapon.secondaryEffect.
Ex: %weapon.secondaryEffect = “poisonEffect”;

The “poisonEffect” is the function name that is called whenever an attack penetrates the armour of the target. The function can look like this:

function poisonEffect(%attacker, %attackingObject, %defender)
{
	%statusEffect = createStatusEffect(%attackingObject.type, %attackingObject.duration, %attackingObject.value, %attackingObject.value, true, %defender, "currentHealth");
	%statusEffect.setTimerOn(1000);
	%defender.statusEffects = %defender.statusEffects SPC %statusEffect;
	%defender.statusEffects = trim(%defender.statusEffects);
}

a. The status effect is created. The %statusEffect is a sceneObject defined in statusEffects.cs in the function createStatusEffect(%type, %durationEnd, %oneTimeValue, %ongoingValue, %damaging, %target, %targetFieldName). It looks like this:

function createStatusEffect(%type, %durationEnd, %oneTimeValue, %ongoingValue, %damaging, %target, %targetFieldName)
{
	%statusEffect = new t2dSceneObject()
	{
		canSaveDynamicFields = "1";
		class = "statusEffectClass";
		type = %type;
		damaging = %damaging;
		duration = 0;
		durationEnd = %durationEnd;
		oneTimeValue = %oneTimeValue;//if the effect is a one time thing then set this value.
		ongoingValue = %ongoingValue;//if the effect should be applied every second then set this value. It should be 0 if it is not applied more than once.
		target = %target;
		targetFieldName = %targetFieldName;//this is the name of the dynamic field that has been changed. That change is made in the function that calls this function to create the status effect sceneobject.
	};
	
	return %statusEffect;
}

b. A timer is then set on the %statusEffect which keeps track of who it affects, how long the status effect is applied, how strong the effect is, if the effect is applied once or if it is cumulative every round and which dynamic field that was altered.

c. The status effect is then added to a list in %defender.statusEffects so it is possible to keep track of all status effects that are applied to any creature, player or monster.

2. If the secondary effect has an effect over time, then you need to assign a secondary effect Object. Assign the secondary effect Object to %weapon.secondaryEffectObject with the function createMonsterSecondaryEffect() found in secondaryEffects.cs. The object created is a script object and holds the variables: duration, value, type, and effect which are needed for the timer to keep track of how long it should run.

Ex:

case "snake poison":
%effect = new scriptObject()
	{
		duration = 5;
		value = 1;
		type = "poison";
		effect = "poisonEffect";
	};

a. Duration is the value in seconds that the secondary effect should last.

b. Value is how much the secondary effect is altering a dynamic field. The “snake poison” effect, for example, affects the dynamic field “currentHealth” with a value of 1 every second. If the secondary effect would be a healing effect, then the Value would be “-1” instead.

c. The type is what type of status effect it is. It can be used to check so that not more than one of the same type is applied to one target.

d. The effect is the name of the function that is used to apply the effect. This is not used for anything.

Advertisements
Posted in Scripting | Tagged , | Leave a comment

Renderorder

Because the perspective of the game is almost isometric the character will sometimes be behind an object and other times in front of the object. The problem here is that when the levels are designed each object is on a particular render layer which means that the player will either always be infront of the object or behind it.

I think I have written a function that should switch the render layer of the moving object(player) and the static object so that the player can dynamically be behind or in front of the object.

%collisionObjects = sceneGraph.pickRadius($player.getPositionX(), $player.getPositionY(), 2);
%maxObjects = getWordCount(%collisionObjects);

for(%i = 0; %i < %maxobjects; %i++)
{
	%current = getWord(%collisionObjects),%i);
	if(%current.class $= "collisionObject)
	{
		verticalRenderOrder($player, %current);
		horisontalRenderOrder($player, %current);
	}
}

function verticalRenderOrder(%movingObject, %staticObject)
{
	if(%movingObject.getPositionY() > %staticObject.getPositionY())
	{
		%movingObject.setLayer(%staticObject.getLayer() - 1);
	}else
	{
		%movingObject.setLayer(%staticObject.getLayer() + 1);
	}
}

//switch horisontal layering
function horisontalRenderOrder(%movingObject, %staticObject)
{
	if(%movingObject.getPositionX() > %staticObject.getPositionX())
	{
		%movingObject.setLayer(%staticObject.getLayer() - 1);
	}else
	{
		%movingObject.setLayer(%staticObject.getLayer() + 1);
	}
}

I think that I should be able to run this when the character moves.

Posted in Scripting | Tagged , , , | 4 Comments

All behaviours so far

Earlier posts have been code that I have not checked. The code below however is code that is fully working and the monster behaves as you would expect.

function trackScent(%monster)
{
	%tSceneGraph = sceneWindow2D.getSceneGraph();
	//%scentCount = new SimSet();
	%scentCount = %tSceneGraph.pickRadius(%monster.getPositionX(), %monster.getPositionY(), 10 + %monster.hearing);
	%maxObjects = getWordCount(%scentCount);
	for(%i = 0; %i <= %maxObjects; %i++)
	{
		%object = getWord(%scentCount, %i);
		if(%object.class $= "PlayerCharacter")
		{
			monsterIsThreathened(%monster, pCharacter);
		}else if(%object.class $= "food")
		{
			%count += 1;
			%distanceX = mAbs(%monster.getPositionX() - %object.getPositionX());
			%distanceY = mAbs(%monster.getPositionY() - %object.getPositionY());
			%distanceH = mSqrt(mPow(%distanceX,2) + mPow(%distanceY,2));
			if(%distanceH < $shortestDistanceH || %count == 1)
			{
				$shortestDistance = %object;
				$shortestDistanceX = mAbs(%monster.getPositionX() - $shortestDistance.getPositionX());
				$shortestDistanceY = mAbs(%monster.getPositionY() - $shortestDistance.getPositionY());
				$shortestDistanceH = mSqrt(mPow($shortestDistanceX,2) + mPow($shortestDistanceY,2));
			}
			
		}
		if(%i == %maxObjects && $shortestDistance !$= "")
		{
			%monster.moveTo($shortestDistance.getPositionX(), $shortestDistance.getPositionY(), $combatMovementSpeed, true, true, false);
		}
	}
}

function monsterClass::onPositionTarget(%this)
{
	$shortestDistance.safeDelete();
	trackScent(%this);
}


function monsterIsThreathened(%monster, %threat)
{
	%choice = dice(1,3,1);
	
	switch(%choice)
	{
		case 1:
			removeThreat(%monster, %threat); 
		case 2:
			echo("change location");
			changeLocation(%monster, %threat);
		case 3:
			echo("monster panic");
			monsterPanic(%monster, %threat);
	}
}

function removeThreat(%monster, %threat)
{
	%detected = isDetected(%monster, %threat);
	echo("monster is detected:" SPC %detected);
	if(%detected)
	{
		startEndCombatMode();
	}else
	{
		monsterAttackTarget(%monster, %threat);
	}
}

function isDetected(%hidingTarget, %spotingTarget)
{
	%hearingCheck = dice(1,10,1) + %spotingTarget.hearing;
	%hideCheck = dice(1,10,1) + %hidingTarget.hide;
	if(%hideCheck < %hearingCheck)
	{
		return(true);
	}else
	{
		return(false);
	}
}
	


function changeLocation(%monster, %threat)
{
	%monsterPosX = %monster.getPositionX();
	%monsterPosY = %monster.getPositionY();
	%threatPosX = %threat.getPositionX();
	%threatPosY = %threat.getPositionY();
	
	%distanceX = %monsterPosX - %threatPosX;
	%distanceY = %monsterPosY - %threatPosY;
	
	%monster.moveTo(%monsterPosX + %distanceX, %monsterPosY + %distanceY, %monster.runSpeed, true, false, false);
}



function monsterPanic(%monster, %threat)
{
	%choice = dice(1,3,1);
	
	switch(%choice)
	{
		case 1:
			changeLocation(%monster, %threat);
		case 2:
			paralyse(%monster);
			echo(%monster.isParalysed);
		case 3:
			removeThreat(%monster, %threat);
	}
}

function paralyse(%target)
{
	%target.isParalysed = true;
}
Posted in Scripting | Tagged , , , | 7 Comments

Monster behaviours

I have started to write some behaviours for monsters, that I hope can describe their lives in the world. Below are some examples of untested code. The monsterIsThreathened function will run as the monster is moving. A monster could be moving if, for example, it is hungry. It will then use its best ability, such as tracking a scent trail left by other animals or the player character, to find food. Then, as soon as it comes close to something and the monster determines it as a threat, the below function will run. That is the idea anyway.

function monsterIsThreathened(%monster)
{
	%choice = dice(1,3,1);

	switch(%choice)
	{
		%choice = 1:
			removeThreat(%monster);
		%choice = 2:
			changeLocation(%monster);
		%choice = 3:
			monsterPanic(%monster);
	}
}

The removeThreat function runs when %choice is 2 in the above function. It will first check if the threat it is stumbled upon has detected it. If not it will attack out of sight. If the monster instead is detected by the player character the game will go into combat mode. Combat mode is a turn-based mode.

function removeThreat(%monster, %threat)
{
	%detected = isDetected(%monster, %threat);
	if(%detected)
	{
		$combatMode = true;
		combatMode();
	}else
	{
		monsterAttackTarget(%monster, %threat);
	}
}

If the monster finds that the best solution is to run away from the threat the line below that runs the function moveTo will make the monster run in the opposite direction, no matter what the coordinates of the threat is.

function changeLocation(%monster,%threat)
{
	%monsterPosX = %monster.getPositionX();
	%monsterPosY = %monster.getPositionY();
	%threatPosX = %threat.getPositionX();
	%threatPosY = %^threat.getPositionY();

	%distanceX = %monsterPosX - %threatPosX;
	%distanceY = %monsterPosY - %threatPosY;

	%monster.moveTo(%monsterPosX + %distanceX, %monsterPosY + %distanceY, %monster.runSpeed, false, false, false);
}

The next monsterPanic almost feels redundant but it also feel plausible so it might work fine.

function monsterPanic(%monster);
{
	%choice = dice(1,3,1);

	switch(%choice)
	{
		%choice = 1:
			changeLocation(%monster, %threat);
		%choice = 2:
			paralyse(%target);
		%choice = 3:
			removeThreat(%monster, %threat)
	}
}
Posted in Scripting | Tagged , , , | 2 Comments

The shape of a sword

The below formula will adjust the effective mass of a sword according to its shape.

H8 = Center Of Mass

E8 = Weapon Shape

=3/H8 + (0.0003*POWER(H8,3) – 0.0118*POWER(H8,2) + 0.0982*H8 + 0.1348)*E8/10

 

What this will do is to return more weapon mass the closer towards the sword tip the impact point is in regards to the weapons Shape quality. The higher Shape Quality the less diminishing the returns will be.

Posted in Scripting | Tagged , , | 2 Comments

sword damage

=========================================
melee damage
=========================================
function swordImpactPoint(%sword, %character, %dice)
{
%length = %sword.length / 10;
%impactPoint = ( (%character.swordSkill + %dice) / 2 ) + %sword.COM;
return(%impactPoint);
}

function swordEffectiveSpeed(%sword, %character)
{
%effectiveSpeed = ( ( ( ( %character.strength + %character.swordSkill ) – (

%sword.weight/(%character.strength/2) ) + (%sword.shape/5) ) + 10) *

((swordImpactPoint()/10) * %sword.length) ) / 4;
return(%effectiveSpeed);
}

function swordEffectiveMass(%sword, %character)
{
%effectiveMass( ( ( (%character.strength/4) + (%sword.weight * 3) ) * ( (%sword.COM

– %sword.handlePosition) / (swordImpactPoint – %sword.COM) ) ) + ( %sword.weight * 2)
return(%effectiveMass);
}

function swordKineticEnergy(%sword, %character)
{
%mass = swordEffectiveMass(%sword, %character);
%velocity = swordEffectiveSpeed(%sword, %character);
%kineticEnergy = %mass * %velocity * %velocity * 0.5;
return(%kineticEnergy);
}

function swordMomentum(%sword, %character)
%mass = swordEffectiveMass(%sword, %character);
%velocity = swordEffectiveSpeed(%sword, %character);
%momentum = %mass * %velocity;
return(%momentum);
}

Posted in Scripting | Tagged , , , , | Leave a comment

inventory

This code should register items dropped on the inventory window as a member of $inventoryWeapons SimSet.

 

function bowWeaponClass::onMouseUp(%this, %modifier, %worldPosition, %mouseClicks)
{
if(inventory.getIsPointInObject(%this.getPositionX,%this.getPositionY))
{
$inventoryWeapons.add(%this);
}
}

 

And this code should arrange all objects that are members of $inventoryWeapons, when the inventory is opened.

 

function showHideInventory(%items)
{
%localPoint = inventory.getAreaMin();

%rows = 4;
%columns = 8;

%rowCount = 1;

%numberOfWeaponsInInventory = $inventoryWeapons.getCount();

%cellWidth = inventory.getSizeX() / %rows;
%cellHeight = inventory.getSizeY() / %columns;

for(%i = 0; %i<=%numberOfWeaponsInInventory; %i++)
{

%item = $weaponsInventory.getObject(%i);
%item.setPositionX( %localPoint.x + %cellWidth * %rowCount );
%item.setPositionY( %localPoint.y + %cellHeight * mCeil( (%i+1) / %rows ) );
%rowCount += 1;

if(%rowCount == 4)
{
%rowCount = 1;
}
}

}

Posted in Scripting | Tagged , , , | Leave a comment

setting the position of inventory items

%localPoint = inventory.getLocalPoint(inventory.getPositionX(), inventory.getPositionY());

%localPointX = %localPoint.x – inventory.getSizeX() / 2;

%localPointY = %localPoint.y – inventory.getSizeY() / 2;

%rows = 4;
%columns = 8;

%rowWidth = inventory.getSizeX() / %rows;
%columnHeight = inventory.getSizeY() / %columns;

for(%i = 0; %i<=%rows; %i++)
{
if(%i  <= %rows)
{
%item = $weaponsInventory.getObject(%i);
%item.setPositionX( %localPointX + ( %rows * (%i +1) ) );
%item.setPositionY( %localPointY + mCeil( (%i + 1) / %columns ) )
}
}

Posted in Scripting | Tagged , , , , | Leave a comment

highlighting monsters

I think this might make a nice and functional effect when hoovering over a monster:

 

function monsterClass::onMouseEnter(%this, %modifier, %worldPosition, %mouseClicks)
{
%this.setBlendColor(0.5, 0.3, 0.7, 1);
}

function monsterClass::onMouseLeave(%this, %modifier, %worldPosition, %mouseClicks)
{
%this.setBlendColor(1, 1, 1, 1);
}

Posted in Scripting | Tagged , , | Leave a comment

finding all monsters to be included in an encounter

According to my research the below code should find all objects on the scene and then put all objects with class name “monsterClass” into an array.

 

function combatModeStart()
{
%tSceneGraph = sceneWindow2D.getSceneGraph();
%monsterCount = %tSceneGraph.pickRadius(0, 0, 50);
for(%i = 0; %i <= getWordCount(%monsterCount); %i++)
{
if(%monsterCount.class $= “monsterClass”)
{
%enounterGroup[%i] = %monsterCount;
}
}
return(%encounterGroup[i]);
echo(listObjects(%encounterGroup));
}

 

I want to get home and try it!!!

Posted in Scripting | Tagged , , , | Leave a comment