Make monster aggression a property per monster type (instead of being derived from the monster class)

* Add property movementAggressionType on MonsterType, that gets read when deserializing monster types from json.
* Add dropdown in monster editor in content editor, to set the monster aggression type.
This commit is contained in:
Oskar Wiksten
2013-04-13 12:50:19 +02:00
parent 7476bb3432
commit 9b66c604e6
8 changed files with 29 additions and 18 deletions

View File

@@ -327,14 +327,15 @@ public final class CombatController implements VisualEffectCompletedCallback {
return true;
}
private static boolean shouldMoveMonsterInCombat(Monster m, MonsterSpawnArea a, Coord playerPosition) {
if (m.aggressionType == MonsterType.AGGRESSIONTYPE_NONE) return false;
final int movementAggressionType = m.getMovementAggressionType();
if (movementAggressionType == MonsterType.AGGRESSIONTYPE_NONE) return false;
if (!m.hasAPs(m.getMoveCost())) return false;
if (m.position.isAdjacentTo(playerPosition)) return false;
if (m.aggressionType == MonsterType.AGGRESSIONTYPE_PROTECT_SPAWN) {
if (movementAggressionType == MonsterType.AGGRESSIONTYPE_PROTECT_SPAWN) {
if (a.area.contains(playerPosition)) return true;
} else if (m.aggressionType == MonsterType.AGGRESSIONTYPE_HELP_OTHERS) {
} else if (movementAggressionType == MonsterType.AGGRESSIONTYPE_HELP_OTHERS) {
for (Monster o : a.monsters) {
if (o == m) continue;
if (o.rectPosition.isAdjacentTo(playerPosition)) return true;

View File

@@ -101,7 +101,7 @@ public final class MonsterMovementController implements EvaluateWalkable {
}
private void determineMonsterNextPosition(Monster m, MonsterSpawnArea area, Coord playerPosition) {
if (m.aggressionType == MonsterType.AGGRESSIONTYPE_PROTECT_SPAWN) {
if (m.getMovementAggressionType() == MonsterType.AGGRESSIONTYPE_PROTECT_SPAWN) {
if (area.area.contains(playerPosition)) {
if (findPathFor(m, playerPosition)) return;
}
@@ -114,7 +114,7 @@ public final class MonsterMovementController implements EvaluateWalkable {
);
}
private void cancelCurrentMonsterMovement(final Monster m) {
private static void cancelCurrentMonsterMovement(final Monster m) {
m.movementDestination = null;
m.nextActionTime += getMillisecondsPerMove(m) * Constants.rollValue(Constants.monsterWaitTurns);
}

View File

@@ -16,7 +16,7 @@ import com.gpl.rpg.AndorsTrail.util.CoordRect;
import com.gpl.rpg.AndorsTrail.util.Range;
public final class Monster extends Actor {
public Coord movementDestination = null;
public long nextActionTime = 0;
public final CoordRect nextPosition;
@@ -24,14 +24,11 @@ public final class Monster extends Actor {
private boolean forceAggressive = false;
private ItemContainer shopItems = null;
public final int aggressionType;
private final MonsterType monsterType;
public Monster(MonsterType monsterType) {
super(monsterType.tileSize, false, monsterType.isImmuneToCriticalHits());
this.monsterType = monsterType;
this.aggressionType = monsterType.aggressionType;
this.iconID = monsterType.iconID;
this.nextPosition = new CoordRect(new Coord(), monsterType.tileSize);
resetStatsToBaseTraits();
@@ -61,7 +58,8 @@ public final class Monster extends Actor {
public String getMonsterTypeID() { return monsterType.id; }
public String getFaction() { return monsterType.faction; }
public int getMonsterClass() { return monsterType.monsterClass; }
public int getMovementAggressionType() { return monsterType.aggressionType; }
public void createLoot(Loot container, Player player) {
int exp = this.getExp();
exp += exp * player.getSkillLevel(SkillCollection.SKILL_MORE_EXP) * SkillCollection.PER_SKILLPOINT_INCREASE_MORE_EXP_PERCENT / 100;

View File

@@ -26,7 +26,7 @@ public final class MonsterType {
public final String faction;
public final int monsterClass;
public final int aggressionType;
public final Size tileSize;
public final int iconID;
public final int maxAP;
@@ -51,6 +51,7 @@ public final class MonsterType {
boolean isUnique,
String faction,
int monsterClass,
int aggressionType,
Size tileSize,
int iconID,
int maxAP,
@@ -73,6 +74,7 @@ public final class MonsterType {
this.faction = faction;
this.isUnique = isUnique;
this.monsterClass = monsterClass;
this.aggressionType = aggressionType;
this.tileSize = tileSize;
this.iconID = iconID;
this.maxAP = maxAP;
@@ -86,14 +88,13 @@ public final class MonsterType {
this.blockChance = blockChance;
this.damageResistance = damageResistance;
this.onHitEffects = onHitEffects;
this.aggressionType = getAggressionType(monsterClass);
}
public static final int AGGRESSIONTYPE_NONE = 0;
public static final int AGGRESSIONTYPE_HELP_OTHERS = 1; // Will move to help if the player attacks some other monster in the same spawn.
public static final int AGGRESSIONTYPE_PROTECT_SPAWN = 2; // Will move to attack if the player stands inside the spawn.
private static int getAggressionType(int monsterClass) {
public static final int AGGRESSIONTYPE_PROTECT_SPAWN = 2; // Will move to attack if the player stands inside the spawn.
private static int getSuggestedAggressionType(int monsterClass) {
switch (monsterClass) {
case MONSTERCLASS_CONSTRUCT:
case MONSTERCLASS_GIANT:
@@ -114,8 +115,8 @@ public final class MonsterType {
public boolean isImmuneToCriticalHits() {
if (monsterClass == MONSTERCLASS_GHOST) return true;
else if (monsterClass == MONSTERCLASS_UNDEAD) return true;
else if (monsterClass == MONSTERCLASS_DEMON) return true;
if (monsterClass == MONSTERCLASS_UNDEAD) return true;
if (monsterClass == MONSTERCLASS_DEMON) return true;
return false;
}

View File

@@ -55,6 +55,7 @@ public final class MonsterTypeParser extends JsonCollectionParserFor<MonsterType
, o.optInt(JsonFieldNames.Monster.unique, 0) > 0
, o.optString(JsonFieldNames.Monster.faction, null)
, o.optInt(JsonFieldNames.Monster.monsterClass, MonsterType.MONSTERCLASS_HUMANOID)
, o.optInt(JsonFieldNames.Monster.movementAggressionType, MonsterType.AGGRESSIONTYPE_NONE)
, ResourceParserUtils.parseSize(o.optString(JsonFieldNames.Monster.size, null), size1x1) //TODO: This could be loaded from the tileset size instead.
, ResourceParserUtils.parseImageID(tileLoader, o.getString(JsonFieldNames.Monster.iconID))
, maxAP

View File

@@ -109,6 +109,7 @@ public final class JsonFieldNames {
public static final String spawnGroup = "spawnGroup";
public static final String size = "size";
public static final String monsterClass = "monsterClass";
public static final String movementAggressionType = "movementAggressionType";
public static final String unique = "unique";
public static final String faction = "faction";
public static final String maxHP = "maxHP";

View File

@@ -34,6 +34,7 @@ var ATEditor = (function(ATEditor, _) {
,moveCost: 10
,unique: 0
,monsterClass: 0
,movementAggressionType: 0
,attackDamage: {}
,hitEffect: { increaseCurrentHP: {}, increaseCurrentAP: {}, conditionsSource: [], conditionsTarget: [] }
}

View File

@@ -65,6 +65,14 @@
<label for="faction" class="hint hint--top" data-hint="Used for making whole groups of monsters aggressive from dialogue. Dialogue replies may affect the player's faction ratings, and having rating less than 0 for a faction will make all monsters in a faction automatically attack.">Faction:</label>
<input type="text" size="30" id="faction" ng-model="obj.faction" class="field at-input-id"/>
</div>
<div class="fieldWithLabel" ng-ds-fade="obj.showAdvanced">
<label for="movementAggressionType">Movement in combat:</label>
<select class="field" id="movementAggressionType" ng-model="obj.movementAggressionType">
<option value="0">Does not move in combat</option>
<option value="1">Help others in same spawn area</option>
<option value="2">Move towards player if inside spawn area</option>
</select>
</div>
<div class="fieldWithLabel">
<label class="checkbox"><input type="checkbox" id="hasConversation" ng-model="obj.hasConversation" />Has conversation</label>
</div>