mirror of
https://github.com/OMGeeky/andors-trail.git
synced 2026-01-15 16:20:51 +01:00
WIP 6 - Moved around lots of properties.
This commit is contained in:
@@ -255,7 +255,7 @@ public class BulkSelectionInterface extends Activity implements TextWatcher {
|
||||
if (amount > totalAvailableAmount) return false;
|
||||
|
||||
if (interfaceType == BULK_INTERFACE_BUY) {
|
||||
if (amount * pricePerUnit > world.model.player.inventory.gold) return false;
|
||||
if (amount * pricePerUnit > world.model.player.getGold()) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -215,7 +215,7 @@ public final class ConversationActivity extends Activity implements OnKeyListene
|
||||
return;
|
||||
} else if (phraseID.equalsIgnoreCase(ConversationCollection.PHRASE_SHOP)) {
|
||||
assert(npc != null);
|
||||
assert(npc.dropList != null);
|
||||
assert(npc.getDropList() != null);
|
||||
Intent intent = new Intent(this, ShopActivity.class);
|
||||
intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/shop"));
|
||||
Dialogs.addMonsterIdentifiers(intent, npc);
|
||||
@@ -350,7 +350,7 @@ public final class ConversationActivity extends Activity implements OnKeyListene
|
||||
}
|
||||
s.text = text;
|
||||
s.color = color;
|
||||
s.isPlayerActor = actor != null ? actor.isPlayer : false;
|
||||
s.isPlayerActor = actor != null ? actor == player : false;
|
||||
conversationHistory.add(s);
|
||||
statementList.clearFocus();
|
||||
listAdapter.notifyDataSetChanged();
|
||||
|
||||
@@ -34,9 +34,9 @@ public final class DebugInterface {
|
||||
new DebugButton("dmg", new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View arg0) {
|
||||
world.model.player.combatTraits.damagePotential.set(99, 99);
|
||||
world.model.player.combatTraits.attackChance = 200;
|
||||
world.model.player.combatTraits.attackCost = 1;
|
||||
world.model.player.damagePotential.set(99, 99);
|
||||
world.model.player.attackChance = 200;
|
||||
world.model.player.attackCost = 1;
|
||||
mainActivity.updateStatus();
|
||||
mainActivity.showToast("DEBUG: damagePotential=99, chance=200%, cost=1", Toast.LENGTH_SHORT);
|
||||
}
|
||||
@@ -129,7 +129,7 @@ public final class DebugInterface {
|
||||
public void onClick(View arg0) {
|
||||
world.model.player.baseTraits.maxHP = 200;
|
||||
world.model.player.health.max = world.model.player.baseTraits.maxHP;
|
||||
world.model.player.health.setMax();
|
||||
world.model.player.setMaxHP();
|
||||
world.model.player.conditions.clear();
|
||||
mainActivity.updateStatus();
|
||||
mainActivity.showToast("DEBUG: hp set to max", Toast.LENGTH_SHORT);
|
||||
|
||||
@@ -6,7 +6,6 @@ import com.gpl.rpg.AndorsTrail.R;
|
||||
import com.gpl.rpg.AndorsTrail.context.ViewContext;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.controller.ItemController;
|
||||
import com.gpl.rpg.AndorsTrail.model.CombatTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Player;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.Inventory;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemContainer;
|
||||
@@ -164,14 +163,19 @@ public final class HeroinfoActivity_Inventory extends Activity {
|
||||
|
||||
private void updateTraits() {
|
||||
heroinfo_stats_gold.setText(getResources().getString(R.string.heroinfo_gold, player.inventory.gold));
|
||||
CombatTraits c = player.combatTraits;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ItemController.describeAttackEffect(c.attackChance, c.damagePotential.current, c.damagePotential.max, c.criticalSkill, c.criticalMultiplier, sb);
|
||||
ItemController.describeAttackEffect(
|
||||
player.getAttackChance(),
|
||||
player.getDamagePotential().current,
|
||||
player.getDamagePotential().max,
|
||||
player.getCriticalSkill(),
|
||||
player.getCriticalMultiplier(),
|
||||
sb);
|
||||
heroinfo_stats_attack.setText(sb.toString());
|
||||
|
||||
sb = new StringBuilder();
|
||||
ItemController.describeBlockEffect(c.blockChance, c.damageResistance, sb);
|
||||
ItemController.describeBlockEffect(player.getBlockChance(), player.getDamageResistance(), sb);
|
||||
heroinfo_stats_defense.setText(sb.toString());
|
||||
}
|
||||
|
||||
@@ -281,12 +285,10 @@ public final class HeroinfoActivity_Inventory extends Activity {
|
||||
boolean enabled = true;
|
||||
|
||||
if (world.model.uiSelections.isInCombat) {
|
||||
int ap = world.model.player.reequipCost;
|
||||
int ap = world.model.player.getReequipCost();
|
||||
text = getResources().getString(R.string.iteminfo_action_unequip_ap, ap);
|
||||
if (ap > 0) {
|
||||
if (world.model.player.ap.current < ap) {
|
||||
enabled = false;
|
||||
}
|
||||
enabled = world.model.player.hasAPs(ap);
|
||||
}
|
||||
} else {
|
||||
text = getResources().getString(R.string.iteminfo_action_unequip);
|
||||
@@ -304,7 +306,7 @@ public final class HeroinfoActivity_Inventory extends Activity {
|
||||
final boolean isInCombat = world.model.uiSelections.isInCombat;
|
||||
if (itemType.isEquippable()) {
|
||||
if (isInCombat) {
|
||||
ap = world.model.player.reequipCost;
|
||||
ap = world.model.player.getReequipCost();
|
||||
text = getResources().getString(R.string.iteminfo_action_equip_ap, ap);
|
||||
} else {
|
||||
text = getResources().getString(R.string.iteminfo_action_equip);
|
||||
@@ -312,7 +314,7 @@ public final class HeroinfoActivity_Inventory extends Activity {
|
||||
action = ItemInfoActivity.ITEMACTION_EQUIP;
|
||||
} else if (itemType.isUsable()) {
|
||||
if (isInCombat) {
|
||||
ap = world.model.player.useItemCost;
|
||||
ap = world.model.player.getUseItemCost();
|
||||
text = getResources().getString(R.string.iteminfo_action_use_ap, ap);
|
||||
} else {
|
||||
text = getResources().getString(R.string.iteminfo_action_use);
|
||||
@@ -320,9 +322,7 @@ public final class HeroinfoActivity_Inventory extends Activity {
|
||||
action = ItemInfoActivity.ITEMACTION_USE;
|
||||
}
|
||||
if (isInCombat && ap > 0) {
|
||||
if (world.model.player.ap.current < ap) {
|
||||
enabled = false;
|
||||
}
|
||||
enabled = world.model.player.hasAPs(ap);
|
||||
}
|
||||
|
||||
Dialogs.showItemInfo(HeroinfoActivity_Inventory.this, itemType.id, action, text, enabled, -1);
|
||||
|
||||
@@ -67,7 +67,7 @@ public final class HeroinfoActivity_Skills extends Activity {
|
||||
private void updateSkillList() {
|
||||
TextView listskills_number_of_increases = (TextView) findViewById(R.id.heroinfo_listskills_number_of_increases);
|
||||
|
||||
int numberOfSkillIncreases = player.availableSkillIncreases;
|
||||
int numberOfSkillIncreases = player.getAvailableSkillIncreases();
|
||||
if (numberOfSkillIncreases > 0) {
|
||||
if (numberOfSkillIncreases == 1) {
|
||||
listskills_number_of_increases.setText(R.string.skill_number_of_increases_one);
|
||||
|
||||
@@ -107,10 +107,10 @@ public final class HeroinfoActivity_Stats extends Activity {
|
||||
}
|
||||
|
||||
private void updateTraits() {
|
||||
heroinfo_level.setText(Integer.toString(player.level));
|
||||
heroinfo_totalexperience.setText(Integer.toString(player.totalExperience));
|
||||
heroinfo_level.setText(Integer.toString(player.getLevel()));
|
||||
heroinfo_totalexperience.setText(Integer.toString(player.getTotalExperience()));
|
||||
heroinfo_ap.setText(player.ap.toString());
|
||||
heroinfo_movecost.setText(Integer.toString(player.baseTraits.moveCost));
|
||||
heroinfo_movecost.setText(Integer.toString(player.getMoveCost()));
|
||||
rangebar_hp.update(player.health);
|
||||
rangebar_exp.update(player.levelExperience);
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ public final class LevelUpActivity extends Activity {
|
||||
}
|
||||
|
||||
world.tileManager.setImageViewTile(levelup_title, player);
|
||||
levelup_description.setText(res.getString(R.string.levelup_description, player.level+1));
|
||||
levelup_description.setText(res.getString(R.string.levelup_description, player.getLevel() + 1));
|
||||
if (player.nextLevelAddsNewSkillpoint()) {
|
||||
levelup_adds_new_skillpoint.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
|
||||
@@ -132,7 +132,7 @@ public final class MainActivity extends Activity {
|
||||
final Coord p = world.model.player.nextPosition;
|
||||
Monster m = world.model.currentMap.getMonsterAt(p);
|
||||
if (m == null) return; //Shouldn't happen.
|
||||
m.forceAggressive = true;
|
||||
m.forceAggressive();
|
||||
view.combatController.setCombatSelection(m, p);
|
||||
view.combatController.enterCombat(CombatController.BEGIN_TURN_PLAYER);
|
||||
} else if (resultCode == ConversationActivity.ACTIVITYRESULT_REMOVE) {
|
||||
@@ -163,7 +163,7 @@ public final class MainActivity extends Activity {
|
||||
|
||||
private boolean save(int slot) {
|
||||
final Player player = world.model.player;
|
||||
return Savegames.saveWorld(world, this, slot, getString(R.string.savegame_currenthero_displayinfo, player.level, player.totalExperience, player.inventory.gold));
|
||||
return Savegames.saveWorld(world, this, slot, getString(R.string.savegame_currenthero_displayinfo, player.getLevel(), player.getTotalExperience(), player.getGold()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.gpl.rpg.AndorsTrail.activity;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
import com.gpl.rpg.AndorsTrail.Dialogs;
|
||||
import com.gpl.rpg.AndorsTrail.R;
|
||||
@@ -89,11 +87,11 @@ public final class MonsterInfoActivity extends Activity {
|
||||
monsterinfo_onhiteffects.update(
|
||||
null,
|
||||
null,
|
||||
monster.baseTraits.onHitEffects == null ? null : Arrays.asList(monster.baseTraits.onHitEffects),
|
||||
monster.getOnHitEffectsAsList(),
|
||||
null,
|
||||
false);
|
||||
hp.update(monster.health);
|
||||
monsterinfo_immune_criticals.setVisibility(monster.isImmuneToCriticalHits ? View.VISIBLE : View.GONE);
|
||||
monsterinfo_immune_criticals.setVisibility(monster.isImmuneToCriticalHits() ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
public static int getMonsterDifficultyResource(WorldContext world, Monster monster) {
|
||||
|
||||
@@ -190,7 +190,7 @@ public final class ShopActivity extends TabActivity implements OnContainerItemCl
|
||||
}
|
||||
|
||||
private void updateGc() {
|
||||
String gc = getResources().getString(R.string.shop_yourgold, player.inventory.gold);
|
||||
String gc = getResources().getString(R.string.shop_yourgold, player.getGold());
|
||||
shop_buy_gc.setText(gc);
|
||||
shop_sell_gc.setText(gc);
|
||||
}
|
||||
|
||||
@@ -167,37 +167,43 @@ public class ActorStatsController {
|
||||
public static void applyAbilityEffects(Actor actor, AbilityModifierTraits effects, int multiplier) {
|
||||
if (effects == null) return;
|
||||
|
||||
CombatTraits actorCombatTraits = actor.combatTraits;
|
||||
|
||||
actor.health.addToMax(effects.increaseMaxHP * multiplier);
|
||||
actor.ap.addToMax(effects.increaseMaxAP * multiplier);
|
||||
actor.baseTraits.moveCost += effects.increaseMoveCost * multiplier;
|
||||
actor.moveCost += effects.increaseMoveCost * multiplier;
|
||||
|
||||
actorCombatTraits.attackCost += effects.increaseAttackCost * multiplier;
|
||||
actor.attackCost += effects.increaseAttackCost * multiplier;
|
||||
//criticalMultiplier should not be increased. It is always defined by the weapon in use.
|
||||
actorCombatTraits.attackChance += effects.increaseAttackChance * multiplier;
|
||||
actorCombatTraits.criticalSkill += effects.increaseCriticalSkill * multiplier;
|
||||
actorCombatTraits.damagePotential.add(effects.increaseMinDamage * multiplier, true);
|
||||
actorCombatTraits.damagePotential.addToMax(effects.increaseMaxDamage * multiplier);
|
||||
actorCombatTraits.blockChance += effects.increaseBlockChance * multiplier;
|
||||
actorCombatTraits.damageResistance += effects.increaseDamageResistance * multiplier;
|
||||
actor.attackChance += effects.increaseAttackChance * multiplier;
|
||||
actor.criticalSkill += effects.increaseCriticalSkill * multiplier;
|
||||
actor.damagePotential.add(effects.increaseMinDamage * multiplier, true);
|
||||
actor.damagePotential.addToMax(effects.increaseMaxDamage * multiplier);
|
||||
actor.blockChance += effects.increaseBlockChance * multiplier;
|
||||
actor.damageResistance += effects.increaseDamageResistance * multiplier;
|
||||
|
||||
if (actorCombatTraits.attackCost <= 0) actorCombatTraits.attackCost = 1;
|
||||
if (actorCombatTraits.attackChance < 0) actorCombatTraits.attackChance = 0;
|
||||
if (actor.baseTraits.moveCost <= 0) actor.baseTraits.moveCost = 1;
|
||||
if (actorCombatTraits.damagePotential.max < 0) actorCombatTraits.damagePotential.set(0, 0);
|
||||
if (actor.attackCost <= 0) actor.attackCost = 1;
|
||||
if (actor.attackChance < 0) actor.attackChance = 0;
|
||||
if (actor.moveCost <= 0) actor.moveCost = 1;
|
||||
if (actor.damagePotential.max < 0) actor.damagePotential.set(0, 0);
|
||||
}
|
||||
|
||||
public static void recalculatePlayerCombatTraits(Player player) { recalculateActorCombatTraits(player); }
|
||||
public static void recalculateMonsterCombatTraits(Monster monster) { recalculateActorCombatTraits(monster); }
|
||||
public static void recalculatePlayerCombatTraits(Player player) {
|
||||
player.resetStatsToBaseTraits();
|
||||
ItemController.applyInventoryEffects(player);
|
||||
SkillController.applySkillEffects(player);
|
||||
applyEffectsFromCurrentConditions(player);
|
||||
ItemController.recalculateHitEffectsFromWornItems(player);
|
||||
player.health.capAtMax();
|
||||
player.ap.capAtMax();
|
||||
}
|
||||
public static void recalculateMonsterCombatTraits(Monster monster) {
|
||||
monster.resetStatsToBaseTraits();
|
||||
applyEffectsFromCurrentConditions(monster);
|
||||
monster.health.capAtMax();
|
||||
monster.ap.capAtMax();
|
||||
}
|
||||
private static void recalculateActorCombatTraits(Actor actor) {
|
||||
actor.resetStatsToBaseTraits();
|
||||
if (actor.isPlayer) ItemController.applyInventoryEffects((Player) actor);
|
||||
if (actor.isPlayer) SkillController.applySkillEffects((Player) actor);
|
||||
applyEffectsFromCurrentConditions(actor);
|
||||
if (actor.isPlayer) ItemController.recalculateHitEffectsFromWornItems((Player) actor);
|
||||
actor.health.capAtMax();
|
||||
actor.ap.capAtMax();
|
||||
if (actor.isPlayer) recalculatePlayerCombatTraits((Player) actor);
|
||||
else recalculateMonsterCombatTraits((Monster) actor);
|
||||
}
|
||||
|
||||
public void applyConditionsToPlayer(Player player, boolean isFullRound) {
|
||||
@@ -227,7 +233,7 @@ public class ActorStatsController {
|
||||
player.conditions.remove(i);
|
||||
player.conditionListener.onActorConditionRemoved(player, c);
|
||||
}
|
||||
recalculateActorCombatTraits(player);
|
||||
recalculatePlayerCombatTraits(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -398,7 +404,7 @@ public class ActorStatsController {
|
||||
public void applySkillEffectsForNewRound(Player player, PredefinedMap currentMap) {
|
||||
int level = player.getSkillLevel(SkillCollection.SKILL_REGENERATION);
|
||||
if (level > 0) {
|
||||
boolean hasAdjacentMonster = MovementController.hasAdjacentAggressiveMonster(currentMap, player.position);
|
||||
boolean hasAdjacentMonster = MovementController.hasAdjacentAggressiveMonster(currentMap, player);
|
||||
if (!hasAdjacentMonster) {
|
||||
boolean changed = player.health.add(level * SkillCollection.PER_SKILLPOINT_INCREASE_REGENERATION, false);
|
||||
if (changed) view.mainActivity.updateStatus();
|
||||
|
||||
@@ -15,7 +15,6 @@ import com.gpl.rpg.AndorsTrail.context.ViewContext;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.VisualEffectCompletedCallback;
|
||||
import com.gpl.rpg.AndorsTrail.model.AttackResult;
|
||||
import com.gpl.rpg.AndorsTrail.model.CombatTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.ModelContainer;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Actor;
|
||||
@@ -134,7 +133,7 @@ public final class CombatController implements VisualEffectCompletedCallback {
|
||||
|
||||
public boolean canExitCombat() { return getAdjacentMonster() == null; }
|
||||
private Monster getAdjacentMonster() {
|
||||
return MovementController.getAdjacentAggressiveMonster(model.currentMap, model.player.position);
|
||||
return MovementController.getAdjacentAggressiveMonster(model.currentMap, model.player);
|
||||
}
|
||||
|
||||
public void executeMoveAttack(int dx, int dy) {
|
||||
@@ -168,7 +167,7 @@ public final class CombatController implements VisualEffectCompletedCallback {
|
||||
private AttackResult lastAttackResult;
|
||||
private void executePlayerAttack() {
|
||||
if (context.effectController.isRunningVisualEffect()) return;
|
||||
if (!useAPs(model.player.combatTraits.attackCost)) return;
|
||||
if (!useAPs(model.player.getAttackCost())) return;
|
||||
final Monster target = model.uiSelections.selectedMonster;
|
||||
this.currentlyAttackedMonster = target;
|
||||
|
||||
@@ -228,7 +227,7 @@ public final class CombatController implements VisualEffectCompletedCallback {
|
||||
player.ap.add(player.getSkillLevel(SkillCollection.SKILL_CLEAVE) * SkillCollection.PER_SKILLPOINT_INCREASE_CLEAVE_AP, false);
|
||||
player.health.add(player.getSkillLevel(SkillCollection.SKILL_EATER) * SkillCollection.PER_SKILLPOINT_INCREASE_EATER_HEALTH, false);
|
||||
|
||||
model.statistics.addMonsterKill(killedMonster.monsterTypeID);
|
||||
model.statistics.addMonsterKill(killedMonster.getMonsterTypeID());
|
||||
model.player.addExperience(loot.exp);
|
||||
totalExpThisFight += loot.exp;
|
||||
loot.exp = 0;
|
||||
@@ -248,9 +247,9 @@ public final class CombatController implements VisualEffectCompletedCallback {
|
||||
|
||||
private boolean playerHasApLeft() {
|
||||
final Player player = model.player;
|
||||
if (player.hasAPs(player.useItemCost)) return true;
|
||||
if (player.hasAPs(player.combatTraits.attackCost)) return true;
|
||||
if (player.hasAPs(player.baseTraits.moveCost)) return true;
|
||||
if (player.hasAPs(player.getUseItemCost())) return true;
|
||||
if (player.hasAPs(player.getAttackCost())) return true;
|
||||
if (player.hasAPs(player.getMoveCost())) return true;
|
||||
return false;
|
||||
}
|
||||
private void playerActionCompleted() {
|
||||
@@ -266,7 +265,7 @@ public final class CombatController implements VisualEffectCompletedCallback {
|
||||
private void executeCombatMove(final Coord dest) {
|
||||
if (model.uiSelections.selectedMonster != null) return;
|
||||
if (dest == null) return;
|
||||
if (!useAPs(model.player.baseTraits.moveCost)) return;
|
||||
if (!useAPs(model.player.getMoveCost())) return;
|
||||
|
||||
int fleeChanceBias = model.player.getSkillLevel(SkillCollection.SKILL_EVASION) * SkillCollection.PER_SKILLPOINT_INCREASE_EVASION_FLEE_CHANCE_PERCENTAGE;
|
||||
if (Constants.roll100(Constants.FLEE_FAIL_CHANCE_PERCENT - fleeChanceBias)) {
|
||||
@@ -309,15 +308,15 @@ public final class CombatController implements VisualEffectCompletedCallback {
|
||||
|
||||
private Monster determineNextMonster(Monster previousMonster) {
|
||||
if (previousMonster != null) {
|
||||
if (previousMonster.hasAPs(previousMonster.combatTraits.attackCost)) return previousMonster;
|
||||
if (previousMonster.hasAPs(previousMonster.getAttackCost())) return previousMonster;
|
||||
}
|
||||
|
||||
for (MonsterSpawnArea a : model.currentMap.spawnAreas) {
|
||||
for (Monster m : a.monsters) {
|
||||
if (!m.isAgressive()) continue;
|
||||
|
||||
if (m.rectPosition.isAdjacentTo(model.player.position)) {
|
||||
if (m.hasAPs(m.combatTraits.attackCost)) return m;
|
||||
if (m.isAdjacentTo(model.player)) {
|
||||
if (m.hasAPs(m.getAttackCost())) return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -332,7 +331,7 @@ public final class CombatController implements VisualEffectCompletedCallback {
|
||||
endMonsterTurn();
|
||||
return;
|
||||
}
|
||||
currentActiveMonster.useAPs(currentActiveMonster.combatTraits.attackCost);
|
||||
currentActiveMonster.useAPs(currentActiveMonster.getAttackCost());
|
||||
|
||||
context.mainActivity.combatview.updateTurnInfo(currentActiveMonster);
|
||||
Resources r = context.mainActivity.getResources();
|
||||
@@ -407,16 +406,16 @@ public final class CombatController implements VisualEffectCompletedCallback {
|
||||
}
|
||||
|
||||
private static boolean hasCriticalAttack(Actor attacker, Actor target) {
|
||||
if (!attacker.combatTraits.hasCriticalAttacks()) return false;
|
||||
if (target.isImmuneToCriticalHits) return false;
|
||||
if (!attacker.hasCriticalAttacks()) return false;
|
||||
if (target.isImmuneToCriticalHits()) return false;
|
||||
return true;
|
||||
}
|
||||
private static float getAverageDamagePerHit(Actor attacker, Actor target) {
|
||||
float result = (float) (getAttackHitChance(attacker.combatTraits, target.combatTraits)) * attacker.combatTraits.damagePotential.average() / 100;
|
||||
float result = (float) (getAttackHitChance(attacker, target)) * attacker.getDamagePotential().average() / 100;
|
||||
if (hasCriticalAttack(attacker, target)) {
|
||||
result += (float) attacker.combatTraits.getEffectiveCriticalChance() * result * attacker.combatTraits.criticalMultiplier / 100;
|
||||
result += (float) attacker.getEffectiveCriticalChance() * result * attacker.getCriticalMultiplier() / 100;
|
||||
}
|
||||
result -= target.combatTraits.damageResistance;
|
||||
result -= target.getDamageResistance();
|
||||
return result;
|
||||
}
|
||||
private static float getAverageDamagePerTurn(Actor attacker, Actor target) {
|
||||
@@ -424,14 +423,14 @@ public final class CombatController implements VisualEffectCompletedCallback {
|
||||
}
|
||||
private static int getTurnsToKillTarget(Actor attacker, Actor target) {
|
||||
if (hasCriticalAttack(attacker, target)) {
|
||||
if (attacker.combatTraits.damagePotential.max * attacker.combatTraits.criticalMultiplier <= target.combatTraits.damageResistance) return 999;
|
||||
if (attacker.getDamagePotential().max * attacker.getCriticalMultiplier() <= target.getDamageResistance()) return 999;
|
||||
} else {
|
||||
if (attacker.combatTraits.damagePotential.max <= target.combatTraits.damageResistance) return 999;
|
||||
if (attacker.getDamagePotential().max <= target.getDamageResistance()) return 999;
|
||||
}
|
||||
|
||||
float averageDamagePerTurn = getAverageDamagePerTurn(attacker, target);
|
||||
if (averageDamagePerTurn <= 0) return 100;
|
||||
return (int) FloatMath.ceil(target.health.max / averageDamagePerTurn);
|
||||
return (int) FloatMath.ceil(target.getMaxHP() / averageDamagePerTurn);
|
||||
}
|
||||
public static int getMonsterDifficulty(WorldContext world, Monster monster) {
|
||||
// returns [0..100) . 100 == easy.
|
||||
@@ -460,25 +459,25 @@ public final class CombatController implements VisualEffectCompletedCallback {
|
||||
private static final int n = 50;
|
||||
private static final int F = 40;
|
||||
private static final float two_divided_by_PI = (float) (2f / Math.PI);
|
||||
private static int getAttackHitChance(final CombatTraits attacker, final CombatTraits target) {
|
||||
final int c = attacker.attackChance - target.blockChance;
|
||||
private static int getAttackHitChance(final Actor attacker, final Actor target) {
|
||||
final int c = attacker.getAttackChance() - target.getBlockChance();
|
||||
// (2/pi)*atan(..) will vary from -1 to +1 .
|
||||
return (int) (50 * (1 + two_divided_by_PI * (float)Math.atan((float)(c-n) / F)));
|
||||
}
|
||||
|
||||
private AttackResult attack(final Actor attacker, final Actor target) {
|
||||
int hitChance = getAttackHitChance(attacker.combatTraits, target.combatTraits);
|
||||
int hitChance = getAttackHitChance(attacker, target);
|
||||
if (!Constants.roll100(hitChance)) return AttackResult.MISS;
|
||||
|
||||
int damage = Constants.rollValue(attacker.combatTraits.damagePotential);
|
||||
int damage = Constants.rollValue(attacker.getDamagePotential());
|
||||
boolean isCriticalHit = false;
|
||||
if (hasCriticalAttack(attacker, target)) {
|
||||
isCriticalHit = Constants.roll100(attacker.combatTraits.getEffectiveCriticalChance());
|
||||
isCriticalHit = Constants.roll100(attacker.getEffectiveCriticalChance());
|
||||
if (isCriticalHit) {
|
||||
damage *= attacker.combatTraits.criticalMultiplier;
|
||||
damage *= attacker.getCriticalMultiplier();
|
||||
}
|
||||
}
|
||||
damage -= target.combatTraits.damageResistance;
|
||||
damage -= target.getDamageResistance();
|
||||
if (damage < 0) damage = 0;
|
||||
target.health.subtract(damage, false);
|
||||
|
||||
@@ -488,9 +487,10 @@ public final class CombatController implements VisualEffectCompletedCallback {
|
||||
}
|
||||
|
||||
private void applyAttackHitStatusEffects(Actor attacker, Actor target) {
|
||||
if (attacker.baseTraits.onHitEffects == null) return;
|
||||
ItemTraits_OnUse[] onHitEffects = attacker.getOnHitEffects();
|
||||
if (onHitEffects == null) return;
|
||||
|
||||
for (ItemTraits_OnUse e : attacker.baseTraits.onHitEffects) {
|
||||
for (ItemTraits_OnUse e : onHitEffects) {
|
||||
context.actorStatsController.applyUseEffect(attacker, target, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public final class Controller {
|
||||
Dialogs.showMonsterEncounter(view.mainActivity, view, m);
|
||||
}
|
||||
} else {
|
||||
Dialogs.showConversation(view.mainActivity, view, m.phraseID, m);
|
||||
Dialogs.showConversation(view.mainActivity, view, m.getPhraseID(), m);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,7 @@ public final class Controller {
|
||||
player.setMaxAP();
|
||||
player.setMaxHP();
|
||||
if (area != null) {
|
||||
player.spawnPlace = area.id;
|
||||
player.spawnMap = world.model.currentMap.name;
|
||||
player.setSpawnPlace(world.model.currentMap.name, area.id);
|
||||
}
|
||||
for (PredefinedMap m : world.maps.predefinedMaps) {
|
||||
m.resetTemporaryData();
|
||||
|
||||
@@ -39,7 +39,7 @@ public final class ItemController {
|
||||
if (!type.isEquippable()) return;
|
||||
final Player player = model.player;
|
||||
if (model.uiSelections.isInCombat) {
|
||||
if (!player.useAPs(player.reequipCost)) return;
|
||||
if (!player.useAPs(player.getReequipCost())) return;
|
||||
}
|
||||
|
||||
if (!player.inventory.removeItem(type.id, 1)) return;
|
||||
@@ -62,7 +62,7 @@ public final class ItemController {
|
||||
if (player.inventory.isEmptySlot(slot)) return;
|
||||
|
||||
if (model.uiSelections.isInCombat) {
|
||||
if (!player.useAPs(player.reequipCost)) return;
|
||||
if (!player.useAPs(player.getReequipCost())) return;
|
||||
}
|
||||
|
||||
unequipSlot(player, slot);
|
||||
@@ -81,7 +81,7 @@ public final class ItemController {
|
||||
if (!type.isUsable()) return;
|
||||
final Player player = model.player;
|
||||
if (model.uiSelections.isInCombat) {
|
||||
if (!player.useAPs(player.useItemCost)) return;
|
||||
if (!player.useAPs(player.getUseItemCost())) return;
|
||||
}
|
||||
|
||||
if (!player.inventory.removeItem(type.id, 1)) return;
|
||||
@@ -101,8 +101,8 @@ public final class ItemController {
|
||||
public static void applyInventoryEffects(Player player) {
|
||||
ItemType weapon = getMainWeapon(player);
|
||||
if (weapon != null) {
|
||||
player.combatTraits.attackCost = 0;
|
||||
player.combatTraits.criticalMultiplier = weapon.effects_equip.stats.setCriticalMultiplier;
|
||||
player.attackCost = 0;
|
||||
player.criticalMultiplier = weapon.effects_equip.stats.setCriticalMultiplier;
|
||||
}
|
||||
|
||||
applyInventoryEffects(player, Inventory.WEARSLOT_WEAPON);
|
||||
@@ -153,9 +153,9 @@ public final class ItemController {
|
||||
if (effects != null) {
|
||||
ItemTraits_OnUse[] effects_ = new ItemTraits_OnUse[effects.size()];
|
||||
effects_ = effects.toArray(effects_);
|
||||
player.baseTraits.onHitEffects = effects_;
|
||||
player.onHitEffects = effects_;
|
||||
} else {
|
||||
player.baseTraits.onHitEffects = null;
|
||||
player.onHitEffects = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public final class MonsterMovementController {
|
||||
for (MonsterSpawnArea a : model.currentMap.spawnAreas) {
|
||||
for (Monster m : a.monsters) {
|
||||
if (!m.isAgressive()) continue;
|
||||
if (!m.rectPosition.isAdjacentTo(model.player.position)) continue;
|
||||
if (!m.isAdjacentTo(model.player)) continue;
|
||||
|
||||
int aggressionChanceBias = model.player.getSkillLevel(SkillCollection.SKILL_EVASION) * SkillCollection.PER_SKILLPOINT_INCREASE_EVASION_MONSTER_ATTACK_CHANCE_PERCENTAGE;
|
||||
if (Constants.roll100(Constants.MONSTER_AGGRESSION_CHANCE_PERCENT - aggressionChanceBias)) {
|
||||
@@ -50,7 +50,7 @@ public final class MonsterMovementController {
|
||||
}
|
||||
|
||||
private boolean moveMonster(final Monster m, final MonsterSpawnArea area, long currentTime) {
|
||||
m.nextActionTime += m.millisecondsPerMove;
|
||||
m.nextActionTime += getMillisecondsPerMove(m);
|
||||
if (m.movementDestination == null) {
|
||||
// Monster has waited and should start to move again.
|
||||
m.movementDestination = new Coord(m.position);
|
||||
@@ -89,7 +89,11 @@ public final class MonsterMovementController {
|
||||
|
||||
private void cancelCurrentMonsterMovement(final Monster m) {
|
||||
m.movementDestination = null;
|
||||
m.nextActionTime += m.millisecondsPerMove * Constants.rollValue(Constants.monsterWaitTurns);
|
||||
m.nextActionTime += getMillisecondsPerMove(m) * Constants.rollValue(Constants.monsterWaitTurns);
|
||||
}
|
||||
|
||||
private static int getMillisecondsPerMove(Monster m) {
|
||||
return Constants.MONSTER_MOVEMENT_TURN_DURATION_MS * m.getMoveCost() / m.getMaxAP();
|
||||
}
|
||||
|
||||
private static int sgn(int i) {
|
||||
|
||||
@@ -233,7 +233,7 @@ public final class MovementController implements TimedMessageTask.Callback {
|
||||
}
|
||||
|
||||
public static void respawnPlayer(final Resources res, final WorldContext world) {
|
||||
placePlayerAt(res, world, MapObject.MAPEVENT_REST, world.model.player.spawnMap, world.model.player.spawnPlace, 0, 0);
|
||||
placePlayerAt(res, world, MapObject.MAPEVENT_REST, world.model.player.getSpawnMap(), world.model.player.getSpawnPlace(), 0, 0);
|
||||
}
|
||||
|
||||
public static void moveBlockedActors(final WorldContext world) {
|
||||
@@ -304,20 +304,21 @@ public final class MovementController implements TimedMessageTask.Callback {
|
||||
public static void refreshMonsterAggressiveness(final PredefinedMap map, final Player player) {
|
||||
for(MonsterSpawnArea a : map.spawnAreas) {
|
||||
for (Monster m : a.monsters) {
|
||||
if (m.faction == null) continue;
|
||||
if (player.getAlignment(m.faction) < 0) m.forceAggressive = true;
|
||||
String faction = m.getFaction();
|
||||
if (faction == null) continue;
|
||||
if (player.getAlignment(faction) < 0) m.forceAggressive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasAdjacentAggressiveMonster(PredefinedMap map, Coord position) {
|
||||
return getAdjacentAggressiveMonster(map, position) != null;
|
||||
public static boolean hasAdjacentAggressiveMonster(PredefinedMap map, Player player) {
|
||||
return getAdjacentAggressiveMonster(map, player) != null;
|
||||
}
|
||||
public static Monster getAdjacentAggressiveMonster(PredefinedMap map, Coord position) {
|
||||
public static Monster getAdjacentAggressiveMonster(PredefinedMap map, Player player) {
|
||||
for (MonsterSpawnArea a : map.spawnAreas) {
|
||||
for (Monster m : a.monsters) {
|
||||
if (!m.isAgressive()) continue;
|
||||
if (m.rectPosition.isAdjacentTo(position)) return m;
|
||||
if (m.isAdjacentTo(player)) return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -17,17 +17,16 @@ import com.gpl.rpg.AndorsTrail.util.ConstRange;
|
||||
|
||||
public final class SkillController {
|
||||
public static void applySkillEffects(Player player) {
|
||||
CombatTraits combatTraits = player.combatTraits;
|
||||
combatTraits.attackChance += SkillCollection.PER_SKILLPOINT_INCREASE_WEAPON_CHANCE * player.getSkillLevel(SkillCollection.SKILL_WEAPON_CHANCE);
|
||||
combatTraits.damagePotential.addToMax(SkillCollection.PER_SKILLPOINT_INCREASE_WEAPON_DAMAGE_MAX * player.getSkillLevel(SkillCollection.SKILL_WEAPON_DMG));
|
||||
combatTraits.damagePotential.add(SkillCollection.PER_SKILLPOINT_INCREASE_WEAPON_DAMAGE_MIN * player.getSkillLevel(SkillCollection.SKILL_WEAPON_DMG), false);
|
||||
combatTraits.blockChance += SkillCollection.PER_SKILLPOINT_INCREASE_DODGE * player.getSkillLevel(SkillCollection.SKILL_DODGE);
|
||||
combatTraits.damageResistance += SkillCollection.PER_SKILLPOINT_INCREASE_BARKSKIN * player.getSkillLevel(SkillCollection.SKILL_BARKSKIN);
|
||||
if (combatTraits.hasCriticalSkillEffect()) {
|
||||
combatTraits.criticalSkill += combatTraits.criticalSkill * SkillCollection.PER_SKILLPOINT_INCREASE_MORE_CRITICALS_PERCENT * player.getSkillLevel(SkillCollection.SKILL_MORE_CRITICALS) / 100;
|
||||
player.attackChance += SkillCollection.PER_SKILLPOINT_INCREASE_WEAPON_CHANCE * player.getSkillLevel(SkillCollection.SKILL_WEAPON_CHANCE);
|
||||
player.damagePotential.addToMax(SkillCollection.PER_SKILLPOINT_INCREASE_WEAPON_DAMAGE_MAX * player.getSkillLevel(SkillCollection.SKILL_WEAPON_DMG));
|
||||
player.damagePotential.add(SkillCollection.PER_SKILLPOINT_INCREASE_WEAPON_DAMAGE_MIN * player.getSkillLevel(SkillCollection.SKILL_WEAPON_DMG), false);
|
||||
player.blockChance += SkillCollection.PER_SKILLPOINT_INCREASE_DODGE * player.getSkillLevel(SkillCollection.SKILL_DODGE);
|
||||
player.damageResistance += SkillCollection.PER_SKILLPOINT_INCREASE_BARKSKIN * player.getSkillLevel(SkillCollection.SKILL_BARKSKIN);
|
||||
if (player.hasCriticalSkillEffect()) {
|
||||
player.criticalSkill += player.criticalSkill * SkillCollection.PER_SKILLPOINT_INCREASE_MORE_CRITICALS_PERCENT * player.getSkillLevel(SkillCollection.SKILL_MORE_CRITICALS) / 100;
|
||||
}
|
||||
if (combatTraits.hasCriticalMultiplierEffect()) {
|
||||
combatTraits.criticalMultiplier += combatTraits.criticalMultiplier * SkillCollection.PER_SKILLPOINT_INCREASE_BETTER_CRITICALS_PERCENT * player.getSkillLevel(SkillCollection.SKILL_BETTER_CRITICALS) / 100;
|
||||
if (player.hasCriticalMultiplierEffect()) {
|
||||
player.criticalMultiplier += player.criticalMultiplier * SkillCollection.PER_SKILLPOINT_INCREASE_BETTER_CRITICALS_PERCENT * player.getSkillLevel(SkillCollection.SKILL_BETTER_CRITICALS) / 100;
|
||||
}
|
||||
player.ap.addToMax(SkillCollection.PER_SKILLPOINT_INCREASE_SPEED * player.getSkillLevel(SkillCollection.SKILL_SPEED));
|
||||
/*final int berserkLevel = player.getSkillLevel(Skills.SKILL_BERSERKER);
|
||||
@@ -145,7 +144,7 @@ public final class SkillController {
|
||||
|
||||
Player player = world.model.player;
|
||||
|
||||
if (player.combatTraits.attackChance - monster.combatTraits.blockChance > SkillCollection.CONCUSSION_THRESHOLD) {
|
||||
if (player.getAttackChance() - monster.getBlockChance() > SkillCollection.CONCUSSION_THRESHOLD) {
|
||||
if (rollForSkillChance(player, SkillCollection.SKILL_CONCUSSION, SkillCollection.PER_SKILLPOINT_INCREASE_CONCUSSION_CHANCE)) {
|
||||
addConditionToActor(monster, world, "concussion", 1, 5);
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ public final class VisualEffectController {
|
||||
}
|
||||
|
||||
public static void addSplatter(PredefinedMap map, Monster m) {
|
||||
int iconID = getSplatterIconFromMonsterClass(m.monsterClass);
|
||||
int iconID = getSplatterIconFromMonsterClass(m.getMonsterClass());
|
||||
if (iconID > 0) map.splatters.add(new BloodSplatter(iconID, m.position));
|
||||
}
|
||||
|
||||
|
||||
@@ -81,9 +81,9 @@ public class SkillInfo {
|
||||
private int getRequirementActualValue(Player player) {
|
||||
switch (requirementType) {
|
||||
case REQUIREMENT_TYPE_SKILL_LEVEL: return player.getSkillLevel(skillOrStatID);
|
||||
case REQUIREMENT_TYPE_EXPERIENCE_LEVEL: return player.level;
|
||||
case REQUIREMENT_TYPE_COMBAT_STAT: return player.baseTraits.getCombatStats(skillOrStatID);
|
||||
case REQUIREMENT_TYPE_ACTOR_STAT: return player.baseTraits.getActorStats(skillOrStatID);
|
||||
case REQUIREMENT_TYPE_EXPERIENCE_LEVEL: return player.getLevel();
|
||||
case REQUIREMENT_TYPE_COMBAT_STAT: return player.getCombatStats(skillOrStatID);
|
||||
case REQUIREMENT_TYPE_ACTOR_STAT: return player.getActorStats(skillOrStatID);
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,15 @@ import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import android.util.FloatMath;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.model.CombatTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnUse;
|
||||
import com.gpl.rpg.AndorsTrail.model.listeners.ActorConditionListeners;
|
||||
import com.gpl.rpg.AndorsTrail.savegames.LegacySavegameFormatReaderForPlayer.LegacySavegameData_Actor;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
@@ -16,34 +21,68 @@ import com.gpl.rpg.AndorsTrail.util.Range;
|
||||
import com.gpl.rpg.AndorsTrail.util.Size;
|
||||
|
||||
public class Actor {
|
||||
public final ActorTraits baseTraits;
|
||||
public final CombatTraits combatTraits;
|
||||
public final int iconID;
|
||||
public String name;
|
||||
public final Size tileSize;
|
||||
public final Range ap;
|
||||
public final Range health;
|
||||
public final Coord position;
|
||||
public final Coord position = new Coord();
|
||||
public final CoordRect rectPosition;
|
||||
public final boolean isPlayer;
|
||||
private final boolean isImmuneToCriticalHits;
|
||||
protected String name;
|
||||
|
||||
// TODO: Should be privates
|
||||
public final Range ap = new Range();
|
||||
public final Range health = new Range();
|
||||
public final ArrayList<ActorCondition> conditions = new ArrayList<ActorCondition>();
|
||||
public final ActorConditionListeners conditionListener = new ActorConditionListeners();
|
||||
public final boolean isPlayer;
|
||||
public final boolean isImmuneToCriticalHits;
|
||||
public int moveCost;
|
||||
public int attackCost;
|
||||
public int attackChance;
|
||||
public int criticalSkill;
|
||||
public float criticalMultiplier;
|
||||
public final Range damagePotential = new Range();
|
||||
public int blockChance;
|
||||
public int damageResistance;
|
||||
public ItemTraits_OnUse[] onHitEffects;
|
||||
|
||||
public Actor(ActorTraits baseTraits, Size tileSize, boolean isPlayer, boolean isImmuneToCriticalHits) {
|
||||
this.combatTraits = new CombatTraits(baseTraits);
|
||||
this.baseTraits = baseTraits;
|
||||
this.iconID = baseTraits.iconID;
|
||||
public Actor(int iconID, Size tileSize, boolean isPlayer, boolean isImmuneToCriticalHits) {
|
||||
this.iconID = iconID;
|
||||
this.tileSize = tileSize;
|
||||
this.ap = new Range(baseTraits.maxAP, baseTraits.maxAP);
|
||||
this.health = new Range(baseTraits.maxHP, baseTraits.maxHP);
|
||||
this.position = new Coord();
|
||||
this.rectPosition = new CoordRect(position, tileSize);
|
||||
this.rectPosition = new CoordRect(this.position, this.tileSize);
|
||||
this.isPlayer = isPlayer;
|
||||
this.isImmuneToCriticalHits = isImmuneToCriticalHits;
|
||||
}
|
||||
|
||||
public int getAttacksPerTurn() { return combatTraits.getAttacksPerTurn(baseTraits.maxAP); }
|
||||
public boolean isImmuneToCriticalHits() { return isImmuneToCriticalHits; }
|
||||
public String getName() { return name; }
|
||||
public int getMaxAP() { return ap.max; }
|
||||
public int getMaxHP() { return health.max; }
|
||||
public int getMoveCost() { return moveCost; }
|
||||
public int getAttackCost() { return attackCost; }
|
||||
public int getAttackChance() { return attackChance; }
|
||||
public int getCriticalSkill() { return criticalSkill; }
|
||||
public float getCriticalMultiplier() { return criticalMultiplier; }
|
||||
public Range getDamagePotential() { return damagePotential; }
|
||||
public int getBlockChance() { return blockChance; }
|
||||
public int getDamageResistance() { return damageResistance; }
|
||||
public ItemTraits_OnUse[] getOnHitEffects() { return onHitEffects; }
|
||||
public List<ItemTraits_OnUse> getOnHitEffectsAsList() { return onHitEffects == null ? null : Arrays.asList(onHitEffects); }
|
||||
|
||||
public boolean hasAttackChanceEffect_() { return getAttackChance() != 0; }
|
||||
public boolean hasAttackDamageEffect_() { return getDamagePotential().max != 0; }
|
||||
public boolean hasBlockEffect_() { return getBlockChance() != 0; }
|
||||
public boolean hasCriticalSkillEffect() { return getCriticalSkill() != 0; }
|
||||
public boolean hasCriticalMultiplierEffect() { float m = getCriticalMultiplier(); return m != 0 && m != 1; }
|
||||
public boolean hasCriticalAttacks() { return hasCriticalSkillEffect() && hasCriticalMultiplierEffect(); }
|
||||
|
||||
public int getAttacksPerTurn() { return (int) Math.floor(getMaxAP() / getAttackCost()); }
|
||||
public int getEffectiveCriticalChance() { return getEffectiveCriticalChance(getCriticalSkill()); }
|
||||
public static int getEffectiveCriticalChance(int criticalSkill) {
|
||||
if (criticalSkill <= 0) return 0;
|
||||
int v = (int) (-5 + 2 * FloatMath.sqrt(5*criticalSkill));
|
||||
if (v < 0) return 0;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
public boolean isDead() {
|
||||
return health.current <= 0;
|
||||
@@ -54,7 +93,6 @@ public class Actor {
|
||||
public void setMaxHP() {
|
||||
health.setMax();
|
||||
}
|
||||
public String getName() { return name; }
|
||||
|
||||
public boolean useAPs(int cost) {
|
||||
if (ap.current < cost) return false;
|
||||
@@ -71,18 +109,11 @@ public class Actor {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void resetStatsToBaseTraits() {
|
||||
combatTraits.set(baseTraits);
|
||||
health.set(baseTraits.maxHP, health.current);
|
||||
ap.set(baseTraits.maxAP, ap.current);
|
||||
baseTraits.moveCost = baseTraits.baseMoveCost;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ====== PARCELABLE ===================================================================
|
||||
|
||||
/*
|
||||
public Actor(DataInputStream src, WorldContext world, int fileversion, boolean isPlayer, boolean isImmuneToCriticalHits, Size tileSize, ActorTraits baseTraits) throws IOException {
|
||||
this.isPlayer = isPlayer;
|
||||
this.isImmuneToCriticalHits = isImmuneToCriticalHits;
|
||||
@@ -140,5 +171,5 @@ public class Actor {
|
||||
for (ActorCondition c : conditions) {
|
||||
c.writeToParcel(dest, flags);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -5,65 +5,86 @@ import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.controller.Constants;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.DropList;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemContainer;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.Loot;
|
||||
import com.gpl.rpg.AndorsTrail.savegames.LegacySavegameFormatReaderForMonster;
|
||||
import com.gpl.rpg.AndorsTrail.savegames.LegacySavegameFormatReaderForMonster.LegacySavegameData_Monster;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
import com.gpl.rpg.AndorsTrail.util.CoordRect;
|
||||
import com.gpl.rpg.AndorsTrail.util.Range;
|
||||
|
||||
public final class Monster extends Actor {
|
||||
public final String monsterTypeID;
|
||||
|
||||
public final int millisecondsPerMove;
|
||||
public Coord movementDestination = null;
|
||||
public long nextActionTime = 0;
|
||||
public boolean forceAggressive = false;
|
||||
public final CoordRect nextPosition;
|
||||
|
||||
public final String phraseID;
|
||||
public final int exp;
|
||||
public final DropList dropList;
|
||||
public final String faction;
|
||||
private boolean forceAggressive = false;
|
||||
private ItemContainer shopItems = null;
|
||||
public final int monsterClass;
|
||||
|
||||
public Monster(MonsterType monsterType, Coord position) {
|
||||
super(monsterType.baseTraits, monsterType.tileSize, false, monsterType.isImmuneToCriticalHits());
|
||||
this.monsterTypeID = monsterType.id;
|
||||
this.position.set(position);
|
||||
this.millisecondsPerMove = Constants.MONSTER_MOVEMENT_TURN_DURATION_MS / monsterType.baseTraits.getMovesPerTurn();
|
||||
private final MonsterType monsterType;
|
||||
|
||||
public Monster(MonsterType monsterType) {
|
||||
super(monsterType.iconID, monsterType.tileSize, false, monsterType.isImmuneToCriticalHits());
|
||||
this.monsterType = monsterType;
|
||||
this.nextPosition = new CoordRect(new Coord(), monsterType.tileSize);
|
||||
this.phraseID = monsterType.phraseID;
|
||||
this.exp = monsterType.exp;
|
||||
this.dropList = monsterType.dropList;
|
||||
this.faction = monsterType.faction;
|
||||
this.monsterClass = monsterType.monsterClass;
|
||||
resetStatsToBaseTraits();
|
||||
}
|
||||
|
||||
public void resetStatsToBaseTraits() {
|
||||
this.name = monsterType.name;
|
||||
this.ap.set(monsterType.maxAP, monsterType.maxAP);
|
||||
this.health.set(monsterType.maxHP, monsterType.maxHP);
|
||||
this.position.set(position);
|
||||
this.moveCost = monsterType.moveCost;
|
||||
this.attackCost = monsterType.attackCost;
|
||||
this.attackChance = monsterType.attackChance;
|
||||
this.criticalSkill = monsterType.criticalSkill;
|
||||
this.criticalMultiplier = monsterType.criticalMultiplier;
|
||||
if (monsterType.damagePotential != null) this.damagePotential.set(monsterType.damagePotential);
|
||||
else this.damagePotential.set(0, 0);
|
||||
this.blockChance = monsterType.blockChance;
|
||||
this.damageResistance = monsterType.damageResistance;
|
||||
this.onHitEffects = monsterType.onHitEffects;
|
||||
}
|
||||
|
||||
public DropList getDropList() { return monsterType.dropList; }
|
||||
public int getExp() { return monsterType.exp; }
|
||||
public String getPhraseID() { return monsterType.phraseID; }
|
||||
public String getMonsterTypeID() { return monsterType.id; }
|
||||
public String getFaction() { return monsterType.faction; }
|
||||
public int getMonsterClass() { return monsterType.monsterClass; }
|
||||
|
||||
public void createLoot(Loot container, Player player) {
|
||||
int exp = this.exp;
|
||||
int exp = this.getExp();
|
||||
exp += exp * player.getSkillLevel(SkillCollection.SKILL_MORE_EXP) * SkillCollection.PER_SKILLPOINT_INCREASE_MORE_EXP_PERCENT / 100;
|
||||
container.exp += exp;
|
||||
if (this.dropList == null) return;
|
||||
this.dropList.createRandomLoot(container, player);
|
||||
DropList dropList = getDropList();
|
||||
if (dropList == null) return;
|
||||
dropList.createRandomLoot(container, player);
|
||||
}
|
||||
public ItemContainer getShopItems(Player player) {
|
||||
if (shopItems != null) return shopItems;
|
||||
Loot loot = new Loot();
|
||||
shopItems = loot.items;
|
||||
this.dropList.createRandomLoot(loot, player);
|
||||
getDropList().createRandomLoot(loot, player);
|
||||
return shopItems;
|
||||
}
|
||||
public void resetShopItems() {
|
||||
this.shopItems = null;
|
||||
}
|
||||
public boolean isAdjacentTo(Player p) {
|
||||
return this.rectPosition.isAdjacentTo(p.position);
|
||||
}
|
||||
|
||||
public boolean isAgressive() {
|
||||
return phraseID == null || forceAggressive;
|
||||
return getPhraseID() == null || forceAggressive;
|
||||
}
|
||||
|
||||
public void forceAggressive() {
|
||||
forceAggressive = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,44 +98,104 @@ public final class Monster extends Actor {
|
||||
MonsterType monsterType = world.monsterTypes.getMonsterType(monsterTypeId);
|
||||
|
||||
if (fileversion < 25) return LegacySavegameFormatReaderForMonster.readFromParcel_pre_v25(src, fileversion, monsterType);
|
||||
if (fileversion < 33) return LegacySavegameFormatReaderForMonster.readFromParcel_pre_v33(src, world, fileversion, monsterType);
|
||||
//if (fileversion < 33) return LegacySavegameFormatReaderForMonster.readFromParcel_pre_v33(src, world, fileversion, monsterType);
|
||||
|
||||
return new Monster(src, world, fileversion, monsterType);
|
||||
}
|
||||
|
||||
public Monster(DataInputStream src, WorldContext world, int fileversion, MonsterType monsterType) throws IOException {
|
||||
super(src, world, fileversion, false, monsterType.isImmuneToCriticalHits(), monsterType.tileSize, monsterType.baseTraits);
|
||||
this.monsterTypeID = monsterType.id;
|
||||
this.millisecondsPerMove = Constants.MONSTER_MOVEMENT_TURN_DURATION_MS / monsterType.baseTraits.getMovesPerTurn();
|
||||
this.nextPosition = new CoordRect(new Coord(), monsterType.tileSize);
|
||||
this.phraseID = monsterType.phraseID;
|
||||
this.exp = monsterType.exp;
|
||||
this.dropList = monsterType.dropList;
|
||||
this(monsterType);
|
||||
|
||||
boolean readCombatTraits = true;
|
||||
if (fileversion >= 25) readCombatTraits = src.readBoolean();
|
||||
if (readCombatTraits) {
|
||||
this.attackCost = src.readInt();
|
||||
this.attackChance = src.readInt();
|
||||
this.criticalSkill = src.readInt();
|
||||
this.criticalMultiplier = src.readFloat();
|
||||
this.damagePotential.set(new Range(src, fileversion));
|
||||
this.blockChance = src.readInt();
|
||||
this.damageResistance = src.readInt();
|
||||
}
|
||||
|
||||
/*this.name = src.readUTF();*/
|
||||
|
||||
this.ap.readFromParcel(src, fileversion);
|
||||
this.health.readFromParcel(src, fileversion);
|
||||
this.position.readFromParcel(src, fileversion);
|
||||
if (fileversion > 16) {
|
||||
final int numConditions = src.readInt();
|
||||
for(int i = 0; i < numConditions; ++i) {
|
||||
conditions.add(new ActorCondition(src, world, fileversion));
|
||||
}
|
||||
}
|
||||
|
||||
if (fileversion >= 34) {
|
||||
this.moveCost = src.readInt();
|
||||
}
|
||||
this.forceAggressive = src.readBoolean();
|
||||
this.faction = monsterType.faction;
|
||||
this.monsterClass = monsterType.monsterClass;
|
||||
if (src.readBoolean()) {
|
||||
this.shopItems = new ItemContainer(src, world, fileversion);
|
||||
if (fileversion >= 31) {
|
||||
if (src.readBoolean()) {
|
||||
this.shopItems = new ItemContainer(src, world, fileversion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public Monster(LegacySavegameData_Monster savegameData, MonsterType monsterType) {
|
||||
super(savegameData, false);
|
||||
this(monsterType, savegameData.position);
|
||||
this.isPlayer = isPlayer;
|
||||
this.isImmuneToCriticalHits = savegameData.isImmuneToCriticalHits;
|
||||
this.baseTraits = new ActorTraits(savegameData);
|
||||
this.name = savegameData.name;
|
||||
this.iconID = savegameData.iconID;
|
||||
this.tileSize = savegameData.tileSize;
|
||||
this.combatTraits = new CombatTraits(savegameData);
|
||||
this.ap = savegameData.ap;
|
||||
this.health = savegameData.health;
|
||||
this.position = savegameData.position;
|
||||
this.rectPosition = savegameData.rectPosition;
|
||||
this.conditions.addAll(savegameData.conditions);
|
||||
|
||||
|
||||
this.monsterTypeID = monsterType.id;
|
||||
this.millisecondsPerMove = Constants.MONSTER_MOVEMENT_TURN_DURATION_MS / monsterType.baseTraits.getMovesPerTurn();
|
||||
this.nextPosition = new CoordRect(new Coord(), monsterType.tileSize);
|
||||
this.phraseID = monsterType.phraseID;
|
||||
this.exp = monsterType.exp;
|
||||
this.dropList = monsterType.dropList;
|
||||
this.forceAggressive = savegameData.forceAggressive;
|
||||
this.faction = monsterType.faction;
|
||||
this.monsterClass = monsterType.monsterClass;
|
||||
this.shopItems = savegameData.shopItems;
|
||||
}
|
||||
*/
|
||||
|
||||
public void writeToParcel(DataOutputStream dest, int flags) throws IOException {
|
||||
dest.writeUTF(monsterTypeID);
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeUTF(getMonsterTypeID());
|
||||
if (attackCost == monsterType.attackCost
|
||||
&& attackChance == monsterType.attackChance
|
||||
&& criticalSkill == monsterType.criticalSkill
|
||||
&& criticalMultiplier == monsterType.criticalMultiplier
|
||||
&& damagePotential.equals(monsterType.damagePotential)
|
||||
&& blockChance == monsterType.blockChance
|
||||
&& damageResistance == monsterType.damageResistance
|
||||
) {
|
||||
dest.writeBoolean(false);
|
||||
} else {
|
||||
dest.writeBoolean(true);
|
||||
dest.writeInt(attackCost);
|
||||
dest.writeInt(attackChance);
|
||||
dest.writeInt(criticalSkill);
|
||||
dest.writeFloat(criticalMultiplier);
|
||||
damagePotential.writeToParcel(dest, flags);
|
||||
dest.writeInt(blockChance);
|
||||
dest.writeInt(damageResistance);
|
||||
}
|
||||
ap.writeToParcel(dest, flags);
|
||||
health.writeToParcel(dest, flags);
|
||||
position.writeToParcel(dest, flags);
|
||||
dest.writeInt(conditions.size());
|
||||
for (ActorCondition c : conditions) {
|
||||
c.writeToParcel(dest, flags);
|
||||
}
|
||||
dest.writeInt(moveCost);
|
||||
|
||||
dest.writeBoolean(forceAggressive);
|
||||
if (shopItems != null) {
|
||||
dest.writeBoolean(true);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.gpl.rpg.AndorsTrail.model.actor;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.model.item.DropList;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnUse;
|
||||
import com.gpl.rpg.AndorsTrail.util.ConstRange;
|
||||
import com.gpl.rpg.AndorsTrail.util.Size;
|
||||
|
||||
public final class MonsterType {
|
||||
@@ -23,9 +25,20 @@ public final class MonsterType {
|
||||
public final boolean isUnique; // Unique monsters are not respawned.
|
||||
public final String faction;
|
||||
public final int monsterClass;
|
||||
public final ActorTraits baseTraits;
|
||||
public final Size tileSize;
|
||||
|
||||
public final int iconID;
|
||||
public final int maxAP;
|
||||
public final int maxHP;
|
||||
public final int moveCost;
|
||||
public final int attackCost;
|
||||
public final int attackChance;
|
||||
public final int criticalSkill;
|
||||
public final float criticalMultiplier;
|
||||
public final ConstRange damagePotential;
|
||||
public final int blockChance;
|
||||
public final int damageResistance;
|
||||
public final ItemTraits_OnUse[] onHitEffects;
|
||||
|
||||
public MonsterType(
|
||||
String id,
|
||||
String name,
|
||||
@@ -37,7 +50,18 @@ public final class MonsterType {
|
||||
String faction,
|
||||
int monsterClass,
|
||||
Size tileSize,
|
||||
ActorTraits baseTraits) {
|
||||
int iconID,
|
||||
int maxAP,
|
||||
int maxHP,
|
||||
int moveCost,
|
||||
int attackCost,
|
||||
int attackChance,
|
||||
int criticalSkill,
|
||||
float criticalMultiplier,
|
||||
ConstRange damagePotential,
|
||||
int blockChance,
|
||||
int damageResistance,
|
||||
ItemTraits_OnUse[] onHitEffects) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.spawnGroup = spawnGroup;
|
||||
@@ -48,7 +72,18 @@ public final class MonsterType {
|
||||
this.isUnique = isUnique;
|
||||
this.monsterClass = monsterClass;
|
||||
this.tileSize = tileSize;
|
||||
this.baseTraits = baseTraits;
|
||||
this.iconID = iconID;
|
||||
this.maxAP = maxAP;
|
||||
this.maxHP = maxHP;
|
||||
this.moveCost = moveCost;
|
||||
this.attackCost = attackCost;
|
||||
this.attackChance = attackChance;
|
||||
this.criticalSkill = criticalSkill;
|
||||
this.criticalMultiplier = criticalMultiplier;
|
||||
this.damagePotential = damagePotential;
|
||||
this.blockChance = blockChance;
|
||||
this.damageResistance = damageResistance;
|
||||
this.onHitEffects = onHitEffects;
|
||||
}
|
||||
|
||||
public boolean isImmuneToCriticalHits() {
|
||||
@@ -57,4 +92,16 @@ public final class MonsterType {
|
||||
else if (monsterClass == MONSTERCLASS_DEMON) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasCombatStats() {
|
||||
if (attackCost != 10) return true;
|
||||
if (attackChance != 0) return true;
|
||||
if (criticalSkill != 0) return true;
|
||||
if (criticalMultiplier != 0) return true;
|
||||
if (damagePotential.current != 0) return true;
|
||||
if (damagePotential.max != 0) return true;
|
||||
if (blockChance != 0) return true;
|
||||
if (damageResistance != 0) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,24 +3,29 @@ package com.gpl.rpg.AndorsTrail.model.actor;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import android.util.FloatMath;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.controller.ActorStatsController;
|
||||
import com.gpl.rpg.AndorsTrail.controller.Constants;
|
||||
import com.gpl.rpg.AndorsTrail.model.CombatTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.DropListCollection;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.Inventory;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnUse;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemTypeCollection;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.Loot;
|
||||
import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress;
|
||||
import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
|
||||
import com.gpl.rpg.AndorsTrail.savegames.LegacySavegameFormatReaderForPlayer;
|
||||
import com.gpl.rpg.AndorsTrail.savegames.LegacySavegameFormatReaderForPlayer.LegacySavegameData_Player;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
import com.gpl.rpg.AndorsTrail.util.Range;
|
||||
import com.gpl.rpg.AndorsTrail.util.Size;
|
||||
@@ -31,32 +36,56 @@ public final class Player extends Actor {
|
||||
public static final Size DEFAULT_PLAYER_SIZE = new Size(1, 1);
|
||||
public final Coord lastPosition;
|
||||
public final Coord nextPosition;
|
||||
|
||||
// TODO: Should be privates
|
||||
public int level;
|
||||
public int totalExperience;
|
||||
public final PlayerBaseTraits baseTraits = new PlayerBaseTraits();
|
||||
public final Range levelExperience; // ranges from 0 to the delta-amount of exp required for next level
|
||||
public final Inventory inventory;
|
||||
private final HashMap<String, HashSet<Integer> > questProgress = new HashMap<String, HashSet<Integer> >();
|
||||
public int availableSkillIncreases = 0;
|
||||
public int useItemCost;
|
||||
public int reequipCost;
|
||||
|
||||
private int totalExperience;
|
||||
private final HashMap<String, HashSet<Integer> > questProgress = new HashMap<String, HashSet<Integer> >();
|
||||
private final SparseIntArray skillLevels = new SparseIntArray();
|
||||
public String spawnMap;
|
||||
public String spawnPlace;
|
||||
public int availableSkillIncreases = 0;
|
||||
private String spawnMap;
|
||||
private String spawnPlace;
|
||||
private final HashMap<String, Integer> alignments = new HashMap<String, Integer>();
|
||||
|
||||
public class PlayerBaseTraits {
|
||||
public int maxAP;
|
||||
public int maxHP;
|
||||
public int moveCost;
|
||||
public int attackCost;
|
||||
public int attackChance;
|
||||
public int criticalSkill;
|
||||
public float criticalMultiplier;
|
||||
public final Range damagePotential = new Range();
|
||||
public int blockChance;
|
||||
public int damageResistance;
|
||||
public int useItemCost;
|
||||
public int reequipCost;
|
||||
}
|
||||
|
||||
public void resetStatsToBaseTraits() {
|
||||
this.ap.max = this.baseTraits.maxAP;
|
||||
this.health.max = this.baseTraits.maxHP;
|
||||
this.moveCost = this.baseTraits.moveCost;
|
||||
this.attackCost = this.baseTraits.attackCost;
|
||||
this.attackChance = this.baseTraits.attackChance;
|
||||
this.criticalSkill = this.baseTraits.criticalSkill;
|
||||
this.criticalMultiplier = this.baseTraits.criticalMultiplier;
|
||||
this.damagePotential.set(this.baseTraits.damagePotential);
|
||||
this.blockChance = this.baseTraits.blockChance;
|
||||
this.damageResistance = this.baseTraits.damageResistance;
|
||||
this.useItemCost = this.baseTraits.useItemCost;
|
||||
this.reequipCost = this.baseTraits.reequipCost;
|
||||
}
|
||||
|
||||
public Player() {
|
||||
super(
|
||||
new ActorTraits(
|
||||
TileManager.CHAR_HERO
|
||||
, 0 // attackCost
|
||||
, 0 // attackChance
|
||||
, 0 // criticalSkill
|
||||
, 0 // criticalMultiplier
|
||||
, new Range() // damagePotential
|
||||
, 0 // blockChance
|
||||
, 0 // damageResistance
|
||||
, DEFAULT_PLAYER_MOVECOST
|
||||
, null)
|
||||
TileManager.CHAR_HERO
|
||||
, DEFAULT_PLAYER_SIZE
|
||||
, true // isPlayer
|
||||
, false // isImmuneToCriticalHits
|
||||
@@ -68,6 +97,9 @@ public final class Player extends Actor {
|
||||
}
|
||||
|
||||
public void initializeNewPlayer(ItemTypeCollection types, DropListCollection dropLists, String name) {
|
||||
baseTraits.maxAP = 10;
|
||||
baseTraits.maxHP = 25;
|
||||
baseTraits.moveCost = DEFAULT_PLAYER_MOVECOST;
|
||||
baseTraits.attackCost = DEFAULT_PLAYER_ATTACKCOST;
|
||||
baseTraits.attackChance = 60;
|
||||
baseTraits.criticalSkill = 0;
|
||||
@@ -75,18 +107,16 @@ public final class Player extends Actor {
|
||||
baseTraits.damagePotential.set(1, 1);
|
||||
baseTraits.blockChance = 0;
|
||||
baseTraits.damageResistance = 0;
|
||||
baseTraits.maxAP = 10;
|
||||
baseTraits.maxHP = 25;
|
||||
baseTraits.useItemCost = 5;
|
||||
baseTraits.reequipCost = 5;
|
||||
this.name = name;
|
||||
baseTraits.moveCost = DEFAULT_PLAYER_MOVECOST;
|
||||
useItemCost = 5;
|
||||
reequipCost = 5;
|
||||
|
||||
level = 1;
|
||||
totalExperience = 1;
|
||||
availableSkillIncreases = 0;
|
||||
skillLevels.clear();
|
||||
alignments.clear();
|
||||
this.level = 1;
|
||||
this.totalExperience = 1;
|
||||
this.inventory.clear();
|
||||
this.questProgress.clear();
|
||||
this.skillLevels.clear();
|
||||
this.availableSkillIncreases = 0;
|
||||
this.alignments.clear();
|
||||
recalculateLevelExperience();
|
||||
|
||||
Loot startItems = new Loot();
|
||||
@@ -94,11 +124,11 @@ public final class Player extends Actor {
|
||||
inventory.add(startItems);
|
||||
|
||||
if (AndorsTrailApplication.DEVELOPMENT_DEBUGRESOURCES) {
|
||||
spawnMap = "debugmap";
|
||||
spawnPlace = "start";
|
||||
this.spawnMap = "debugmap";
|
||||
this.spawnPlace = "start";
|
||||
} else {
|
||||
spawnMap = "home";
|
||||
spawnPlace = "rest";
|
||||
this.spawnMap = "home";
|
||||
this.spawnPlace = "rest";
|
||||
}
|
||||
|
||||
ActorStatsController.recalculatePlayerCombatTraits(this);
|
||||
@@ -176,20 +206,62 @@ public final class Player extends Actor {
|
||||
alignments.put(faction, newValue);
|
||||
}
|
||||
|
||||
public void setSpawnPlace(String spawnMap, String spawnPlace) {
|
||||
this.spawnPlace = spawnPlace;
|
||||
this.spawnMap = spawnMap;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getReequipCost() { return reequipCost; }
|
||||
public int getUseItemCost() { return useItemCost; }
|
||||
public int getAvailableSkillIncreases() { return availableSkillIncreases; }
|
||||
public int getLevel() { return level; }
|
||||
public int getTotalExperience() { return totalExperience; }
|
||||
public int getGold() { return inventory.gold; }
|
||||
public String getSpawnMap() { return spawnMap; }
|
||||
public String getSpawnPlace() { return spawnPlace; }
|
||||
|
||||
|
||||
public int getActorStats(int statID) {
|
||||
switch (statID) {
|
||||
case ActorTraits.STAT_ACTOR_MAX_HP: return baseTraits.maxHP;
|
||||
case ActorTraits.STAT_ACTOR_MAX_AP: return baseTraits.maxAP;
|
||||
case ActorTraits.STAT_ACTOR_MOVECOST: return baseTraits.moveCost;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
public int getCombatStats(int statID) {
|
||||
switch (statID) {
|
||||
case CombatTraits.STAT_COMBAT_ATTACK_COST: return baseTraits.attackCost;
|
||||
case CombatTraits.STAT_COMBAT_ATTACK_CHANCE: return baseTraits.attackChance;
|
||||
case CombatTraits.STAT_COMBAT_CRITICAL_SKILL: return baseTraits.criticalSkill;
|
||||
case CombatTraits.STAT_COMBAT_CRITICAL_MULTIPLIER: return (int) FloatMath.floor(baseTraits.criticalMultiplier);
|
||||
case CombatTraits.STAT_COMBAT_DAMAGE_POTENTIAL_MIN: return baseTraits.damagePotential.current;
|
||||
case CombatTraits.STAT_COMBAT_DAMAGE_POTENTIAL_MAX: return baseTraits.damagePotential.max;
|
||||
case CombatTraits.STAT_COMBAT_BLOCK_CHANCE: return baseTraits.blockChance;
|
||||
case CombatTraits.STAT_COMBAT_DAMAGE_RESISTANCE: return baseTraits.damageResistance;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ====== PARCELABLE ===================================================================
|
||||
|
||||
public static Player readFromParcel(DataInputStream src, WorldContext world, int fileversion) throws IOException {
|
||||
Player player;
|
||||
/* Player player;
|
||||
if (fileversion < 34) player = LegacySavegameFormatReaderForPlayer.readFromParcel_pre_v34(src, world, fileversion);
|
||||
else player = new Player(src, world, fileversion);
|
||||
*/
|
||||
Player player = new Player(src, world, fileversion);
|
||||
|
||||
LegacySavegameFormatReaderForPlayer.upgradeSavegame(player, world, fileversion);
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
/*
|
||||
public Player(DataInputStream src, WorldContext world, int fileversion) throws IOException {
|
||||
super(src, world, fileversion, true, false, DEFAULT_PLAYER_SIZE, null);
|
||||
this.lastPosition = new Coord(src, fileversion);
|
||||
@@ -229,7 +301,103 @@ public final class Player extends Actor {
|
||||
alignments.put(faction, alignment);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
public Player(DataInputStream src, WorldContext world, int fileversion) throws IOException {
|
||||
this();
|
||||
|
||||
this.name = src.readUTF();
|
||||
this.iconID = src.readInt();
|
||||
|
||||
if (fileversion <= 33) {
|
||||
LegacySavegameFormatReaderForPlayer.readCombatTraitsPreV034(src, fileversion);
|
||||
/*this.iconID = */src.readInt();
|
||||
/*this.tileSize = */new Size(src, fileversion);
|
||||
}
|
||||
|
||||
this.baseTraits.maxAP = src.readInt();
|
||||
this.baseTraits.maxHP = src.readInt();
|
||||
this.moveCost = src.readInt();
|
||||
|
||||
this.baseTraits.attackCost = src.readInt();
|
||||
this.baseTraits.attackChance = src.readInt();
|
||||
this.baseTraits.criticalSkill = src.readInt();
|
||||
if (fileversion <= 20) {
|
||||
this.baseTraits.criticalMultiplier = src.readInt();
|
||||
} else {
|
||||
this.baseTraits.criticalMultiplier = src.readFloat();
|
||||
}
|
||||
this.baseTraits.damagePotential.readFromParcel(src, fileversion);
|
||||
this.baseTraits.blockChance = src.readInt();
|
||||
this.baseTraits.damageResistance = src.readInt();
|
||||
|
||||
if (fileversion <= 16) {
|
||||
this.baseTraits.moveCost = this.moveCost;
|
||||
} else {
|
||||
this.baseTraits.moveCost = src.readInt();
|
||||
}
|
||||
|
||||
this.ap.set(new Range(src, fileversion));
|
||||
this.health.set(new Range(src, fileversion));
|
||||
this.position.set(new Coord(src, fileversion));
|
||||
if (fileversion > 16) {
|
||||
final int n = src.readInt();
|
||||
for(int i = 0; i < n ; ++i) {
|
||||
this.conditions.add(new ActorCondition(src, world, fileversion));
|
||||
}
|
||||
}
|
||||
|
||||
this.lastPosition.readFromParcel(src, fileversion);
|
||||
this.nextPosition.readFromParcel(src, fileversion);
|
||||
this.level = src.readInt();
|
||||
this.totalExperience = src.readInt();
|
||||
this.inventory.readFromParcel(src, world, fileversion);
|
||||
|
||||
if (fileversion <= 13) LegacySavegameFormatReaderForPlayer.readQuestProgressPreV13(this, src, world, fileversion);
|
||||
|
||||
this.useItemCost = src.readInt();
|
||||
this.reequipCost = src.readInt();
|
||||
final int size2 = src.readInt();
|
||||
for(int i = 0; i < size2; ++i) {
|
||||
if (fileversion <= 21) {
|
||||
this.skillLevels.put(i, src.readInt());
|
||||
} else {
|
||||
final int skillID = src.readInt();
|
||||
this.skillLevels.put(skillID, src.readInt());
|
||||
}
|
||||
}
|
||||
this.spawnMap = src.readUTF();
|
||||
this.spawnPlace = src.readUTF();
|
||||
|
||||
if (fileversion > 13) {
|
||||
final int numquests = src.readInt();
|
||||
for(int i = 0; i < numquests; ++i) {
|
||||
final String questID = src.readUTF();
|
||||
this.questProgress.put(questID, new HashSet<Integer>());
|
||||
final int numprogress = src.readInt();
|
||||
for(int j = 0; j < numprogress; ++j) {
|
||||
int progress = src.readInt();
|
||||
this.questProgress.get(questID).add(progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.availableSkillIncreases = 0;
|
||||
if (fileversion > 21) {
|
||||
this.availableSkillIncreases = src.readInt();
|
||||
}
|
||||
|
||||
if (fileversion >= 26) {
|
||||
final int size3 = src.readInt();
|
||||
for(int i = 0; i < size3; ++i) {
|
||||
final String faction = src.readUTF();
|
||||
final int alignment = src.readInt();
|
||||
this.alignments.put(faction, alignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public Player(LegacySavegameData_Player savegameData) {
|
||||
super(savegameData, true);
|
||||
this.lastPosition = savegameData.lastPosition;
|
||||
@@ -250,9 +418,29 @@ public final class Player extends Actor {
|
||||
this.availableSkillIncreases = savegameData.availableSkillIncreases;
|
||||
this.alignments.putAll(savegameData.alignments);
|
||||
}
|
||||
|
||||
*/
|
||||
public void writeToParcel(DataOutputStream dest, int flags) throws IOException {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeUTF(name);
|
||||
dest.writeInt(iconID);
|
||||
dest.writeInt(baseTraits.maxAP);
|
||||
dest.writeInt(baseTraits.maxHP);
|
||||
dest.writeInt(moveCost);
|
||||
dest.writeInt(baseTraits.attackCost);
|
||||
dest.writeInt(baseTraits.attackChance);
|
||||
dest.writeInt(baseTraits.criticalSkill);
|
||||
dest.writeFloat(baseTraits.criticalMultiplier);
|
||||
baseTraits.damagePotential.writeToParcel(dest, flags);
|
||||
dest.writeInt(baseTraits.blockChance);
|
||||
dest.writeInt(baseTraits.damageResistance);
|
||||
dest.writeInt(baseTraits.moveCost);
|
||||
|
||||
ap.writeToParcel(dest, flags);
|
||||
health.writeToParcel(dest, flags);
|
||||
position.writeToParcel(dest, flags);
|
||||
dest.writeInt(conditions.size());
|
||||
for (ActorCondition c : conditions) {
|
||||
c.writeToParcel(dest, flags);
|
||||
}
|
||||
lastPosition.writeToParcel(dest, flags);
|
||||
nextPosition.writeToParcel(dest, flags);
|
||||
dest.writeInt(level);
|
||||
|
||||
@@ -27,6 +27,13 @@ public final class Inventory extends ItemContainer {
|
||||
|
||||
public Inventory() { }
|
||||
|
||||
public void clear() {
|
||||
for(int i = 0; i < NUM_WORN_SLOTS; ++i) wear[i] = null;
|
||||
for(int i = 0; i < NUM_QUICK_SLOTS; ++i) quickitem[i] = null;
|
||||
gold = 0;
|
||||
items.clear();
|
||||
}
|
||||
|
||||
public void add(final Loot loot) {
|
||||
this.gold += loot.gold;
|
||||
this.add(loot.items);
|
||||
@@ -56,26 +63,31 @@ public final class Inventory extends ItemContainer {
|
||||
// ====== PARCELABLE ===================================================================
|
||||
|
||||
public Inventory(DataInputStream src, WorldContext world, int fileversion) throws IOException {
|
||||
super(src, world, fileversion);
|
||||
this.readFromParcel(src, world, fileversion);
|
||||
}
|
||||
public void readFromParcel(DataInputStream src, WorldContext world, int fileversion) throws IOException {
|
||||
super.readFromParcel(src, world, fileversion);
|
||||
gold = src.readInt();
|
||||
|
||||
if (fileversion < 23) LegacySavegameFormatReaderForItemContainer.refundUpgradedItems(this);
|
||||
|
||||
final int size = src.readInt();
|
||||
for(int i = 0; i < size; ++i) {
|
||||
for(int i = 0; i < NUM_WORN_SLOTS; ++i) {
|
||||
wear[i] = null;
|
||||
}
|
||||
final int numWornSlots = src.readInt();
|
||||
for(int i = 0; i < numWornSlots; ++i) {
|
||||
if (src.readBoolean()) {
|
||||
wear[i] = world.itemTypes.getItemType(src.readUTF());
|
||||
} else {
|
||||
wear[i] = null;
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < NUM_QUICK_SLOTS; ++i) {
|
||||
quickitem[i] = null;
|
||||
}
|
||||
if (fileversion >= 19) {
|
||||
final int quickSlots = src.readInt();
|
||||
for(int i = 0; i < quickSlots; ++i) {
|
||||
if (src.readBoolean()) {
|
||||
quickitem[i] = world.itemTypes.getItemType(src.readUTF());
|
||||
} else {
|
||||
quickitem[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,11 @@ public class ItemContainer {
|
||||
// ====== PARCELABLE ===================================================================
|
||||
|
||||
public ItemContainer(DataInputStream src, WorldContext world, int fileversion) throws IOException {
|
||||
readFromParcel(src, world, fileversion);
|
||||
}
|
||||
|
||||
public void readFromParcel(DataInputStream src, WorldContext world, int fileversion) throws IOException {
|
||||
items.clear();
|
||||
final int size = src.readInt();
|
||||
for(int i = 0; i < size; ++i) {
|
||||
ItemEntry entry = new ItemEntry(src, world, fileversion);
|
||||
|
||||
@@ -62,7 +62,9 @@ public final class MonsterSpawnArea {
|
||||
spawn(p, context.monsterTypes.getMonsterType(monsterTypeID));
|
||||
}
|
||||
public void spawn(Coord p, MonsterType type) {
|
||||
monsters.add(new Monster(type, p));
|
||||
Monster m = new Monster(type);
|
||||
m.position.set(p);
|
||||
monsters.add(m);
|
||||
quantity.current++;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,14 +3,13 @@ package com.gpl.rpg.AndorsTrail.resource.parsers;
|
||||
import android.util.FloatMath;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.controller.Constants;
|
||||
import com.gpl.rpg.AndorsTrail.model.CombatTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionTypeCollection;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.ActorTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.MonsterType;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.DropListCollection;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnUse;
|
||||
import com.gpl.rpg.AndorsTrail.resource.DynamicTileLoader;
|
||||
import com.gpl.rpg.AndorsTrail.resource.ResourceFileTokenizer.ResourceParserFor;
|
||||
import com.gpl.rpg.AndorsTrail.util.ConstRange;
|
||||
import com.gpl.rpg.AndorsTrail.util.Pair;
|
||||
import com.gpl.rpg.AndorsTrail.util.Size;
|
||||
|
||||
@@ -30,29 +29,24 @@ public final class MonsterTypeParser extends ResourceParserFor<MonsterType> {
|
||||
|
||||
@Override
|
||||
public Pair<String, MonsterType> parseRow(String[] parts) {
|
||||
final String monsterTypeId = parts[0];
|
||||
final CombatTraits combatTraits = ResourceParserUtils.parseCombatTraits(parts, 11);
|
||||
final ItemTraits_OnUse hitEffect = itemTraitsParser.parseItemTraits_OnUse(parts, 21, true);
|
||||
final ActorTraits baseTraits = new ActorTraits(
|
||||
ResourceParserUtils.parseImageID(tileLoader, parts[1]) // IconID
|
||||
, ResourceParserUtils.parseInt(parts[11], 10) // AttackCost
|
||||
, ResourceParserUtils.parseInt(parts[12], 0) //AttackChance
|
||||
, ResourceParserUtils.parseInt(parts[13], 0) //CriticalSkill
|
||||
, ResourceParserUtils.parseFloat(parts[14], 0) //CriticalMultiplier
|
||||
, ResourceParserUtils.parseRange(parts[15], parts[16]) //DamagePotential
|
||||
, ResourceParserUtils.parseInt(parts[17], 0) //BlockChance
|
||||
, ResourceParserUtils.parseInt(parts[18], 0) //DamageResistance
|
||||
, ResourceParserUtils.parseInt(parts[10], 10) // MoveCost
|
||||
, hitEffect == null ? null : new ItemTraits_OnUse[] { hitEffect }
|
||||
);
|
||||
baseTraits.maxHP = ResourceParserUtils.parseInt(parts[8], 1);
|
||||
baseTraits.maxAP = ResourceParserUtils.parseInt(parts[9], 10);
|
||||
int maxHP = ResourceParserUtils.parseInt(parts[8], 1);
|
||||
int maxAP = ResourceParserUtils.parseInt(parts[9], 10);
|
||||
int attackCost = ResourceParserUtils.parseInt(parts[11], 10);
|
||||
int attackChance = ResourceParserUtils.parseInt(parts[12], 0);
|
||||
ConstRange damagePotential = ResourceParserUtils.parseConstRange(parts[15], parts[16]);
|
||||
int criticalSkill = ResourceParserUtils.parseInt(parts[13], 0);
|
||||
float criticalMultiplier = ResourceParserUtils.parseFloat(parts[14], 0);
|
||||
int blockChance = ResourceParserUtils.parseInt(parts[17], 0);
|
||||
int damageResistance = ResourceParserUtils.parseInt(parts[18], 0);
|
||||
|
||||
final int exp = getExpectedMonsterExperience(combatTraits, hitEffect, baseTraits.maxHP, baseTraits.maxAP);
|
||||
final int exp = getExpectedMonsterExperience(attackCost, attackChance, damagePotential, criticalSkill, criticalMultiplier, blockChance, damageResistance, hitEffect, maxHP, maxAP);
|
||||
|
||||
final String monsterTypeId = parts[0];
|
||||
return new Pair<String, MonsterType>(monsterTypeId, new MonsterType(
|
||||
monsterTypeId
|
||||
, parts[2] // Name
|
||||
, parts[3] // Tags
|
||||
, parts[3] // SpawnGroup
|
||||
, exp // Exp
|
||||
, droplists.getDropList(parts[19]) // Droplist
|
||||
, ResourceParserUtils.parseNullableString(parts[20]) // PhraseID
|
||||
@@ -60,21 +54,45 @@ public final class MonsterTypeParser extends ResourceParserFor<MonsterType> {
|
||||
, ResourceParserUtils.parseNullableString(parts[7]) // Faction
|
||||
, ResourceParserUtils.parseInt(parts[5], MonsterType.MONSTERCLASS_HUMANOID) // MonsterClass
|
||||
, ResourceParserUtils.parseSize(parts[4], size1x1) //TODO: This could be loaded from the tileset size instead.
|
||||
, baseTraits
|
||||
, ResourceParserUtils.parseImageID(tileLoader, parts[1]) // IconID
|
||||
, maxAP
|
||||
, maxHP
|
||||
, ResourceParserUtils.parseInt(parts[10], 10) // MoveCost
|
||||
, attackCost
|
||||
, attackChance
|
||||
, criticalSkill
|
||||
, criticalMultiplier
|
||||
, damagePotential
|
||||
, blockChance
|
||||
, damageResistance
|
||||
, hitEffect == null ? null : new ItemTraits_OnUse[] { hitEffect }
|
||||
));
|
||||
}
|
||||
|
||||
private static float div100(int v) {
|
||||
return (float) v / 100f;
|
||||
}
|
||||
private static int getExpectedMonsterExperience(final CombatTraits t, ItemTraits_OnUse hitEffect, final int maxHP, final int maxAP) {
|
||||
if (t == null) return 0;
|
||||
final float avgAttackHP = t.getAttacksPerTurn(maxAP) * div100(t.attackChance) * t.damagePotential.averagef() * (1 + div100(t.criticalSkill) * t.criticalMultiplier);
|
||||
final float avgDefenseHP = maxHP * (1 + div100(t.blockChance)) + Constants.EXP_FACTOR_DAMAGERESISTANCE * t.damageResistance;
|
||||
private static int getExpectedMonsterExperience(
|
||||
int attackCost,
|
||||
int attackChance,
|
||||
ConstRange damagePotential,
|
||||
int criticalSkill,
|
||||
float criticalMultiplier,
|
||||
int blockChance,
|
||||
int damageResistance,
|
||||
ItemTraits_OnUse hitEffect,
|
||||
final int maxHP,
|
||||
final int maxAP) {
|
||||
final float averageDamage = damagePotential != null ? damagePotential.averagef() : 0;
|
||||
final float avgAttackHP = getAttacksPerTurn(maxAP, attackCost) * div100(attackChance) * averageDamage * (1 + div100(criticalSkill) * criticalMultiplier);
|
||||
final float avgDefenseHP = maxHP * (1 + div100(blockChance)) + Constants.EXP_FACTOR_DAMAGERESISTANCE * damageResistance;
|
||||
int attackConditionBonus = 0;
|
||||
if (hitEffect != null && hitEffect.addedConditions_target != null && hitEffect.addedConditions_target.length > 0) {
|
||||
attackConditionBonus += 50;
|
||||
}
|
||||
return (int) FloatMath.ceil((avgAttackHP * 3 + avgDefenseHP) * Constants.EXP_FACTOR_SCALING) + attackConditionBonus;
|
||||
}
|
||||
private static int getAttacksPerTurn(int maxAP, int attackCost) {
|
||||
return (int) Math.floor(maxAP / attackCost);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public final class TileManager {
|
||||
HashSet<Integer> iconIDs = new HashSet<Integer>();
|
||||
for(MonsterSpawnArea a : map.spawnAreas) {
|
||||
for(String monsterTypeID : a.monsterTypeIDs) {
|
||||
iconIDs.add(world.monsterTypes.getMonsterType(monsterTypeID).baseTraits.iconID);
|
||||
iconIDs.add(world.monsterTypes.getMonsterType(monsterTypeID).iconID);
|
||||
}
|
||||
}
|
||||
iconIDs.addAll(tileMap.usedTileIDs);
|
||||
|
||||
@@ -15,16 +15,17 @@ import com.gpl.rpg.AndorsTrail.util.Range;
|
||||
|
||||
public class LegacySavegameFormatReaderForMonster {
|
||||
public static Monster readFromParcel_pre_v25(DataInputStream src, int fileversion, MonsterType monsterType) throws IOException {
|
||||
Coord position = new Coord(src, fileversion);
|
||||
Monster m = new Monster(monsterType, position);
|
||||
Monster m = new Monster(monsterType);
|
||||
m.position.set(new Coord(src, fileversion));
|
||||
m.ap.current = src.readInt();
|
||||
m.health.current = src.readInt();
|
||||
if (fileversion >= 12) {
|
||||
m.forceAggressive = src.readBoolean();
|
||||
if (src.readBoolean()) m.forceAggressive();
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/*
|
||||
public static Monster readFromParcel_pre_v33(DataInputStream src, WorldContext world, int fileversion, MonsterType monsterType) throws IOException {
|
||||
LegacySavegameData_Monster savegameData = readMonsterDataPreV33(src, world, fileversion, monsterType);
|
||||
return new Monster(savegameData, monsterType);
|
||||
@@ -50,21 +51,21 @@ public class LegacySavegameFormatReaderForMonster {
|
||||
result.damageResistance = src.readInt();
|
||||
}
|
||||
|
||||
result.iconID = monsterType.baseTraits.iconID;
|
||||
result.iconID = monsterType.iconID;
|
||||
result.tileSize = monsterType.tileSize;
|
||||
result.maxAP = monsterType.baseTraits.maxAP;
|
||||
result.maxHP = monsterType.baseTraits.maxHP;
|
||||
result.maxAP = monsterType.maxAP;
|
||||
result.maxHP = monsterType.maxHP;
|
||||
result.name = monsterType.name;
|
||||
result.moveCost = monsterType.baseTraits.moveCost;
|
||||
result.moveCost = monsterType.moveCost;
|
||||
|
||||
result.baseAttackCost = monsterType.baseTraits.attackCost;
|
||||
result.baseAttackChance = monsterType.baseTraits.attackChance;
|
||||
result.baseCriticalSkill = monsterType.baseTraits.criticalSkill;
|
||||
result.baseCriticalMultiplier = monsterType.baseTraits.criticalMultiplier;
|
||||
result.baseDamagePotential = monsterType.baseTraits.damagePotential;
|
||||
result.baseBlockChance = monsterType.baseTraits.blockChance;
|
||||
result.baseDamageResistance = monsterType.baseTraits.damageResistance;
|
||||
result.baseMoveCost = monsterType.baseTraits.baseMoveCost;
|
||||
result.baseAttackCost = monsterType.attackCost;
|
||||
result.baseAttackChance = monsterType.attackChance;
|
||||
result.baseCriticalSkill = monsterType.criticalSkill;
|
||||
result.baseCriticalMultiplier = monsterType.criticalMultiplier;
|
||||
result.baseDamagePotential = new Range(monsterType.damagePotential);
|
||||
result.baseBlockChance = monsterType.blockChance;
|
||||
result.baseDamageResistance = monsterType.damageResistance;
|
||||
result.baseMoveCost = monsterType.moveCost;
|
||||
|
||||
if (!readCombatTraits) {
|
||||
result.attackCost = result.baseAttackCost;
|
||||
@@ -101,5 +102,5 @@ public class LegacySavegameFormatReaderForMonster {
|
||||
// from Monster
|
||||
public boolean forceAggressive;
|
||||
public ItemContainer shopItems;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.gpl.rpg.AndorsTrail.util.Range;
|
||||
import com.gpl.rpg.AndorsTrail.util.Size;
|
||||
|
||||
public final class LegacySavegameFormatReaderForPlayer {
|
||||
/*
|
||||
public static Player readFromParcel_pre_v34(DataInputStream src, WorldContext world, int fileversion) throws IOException {
|
||||
LegacySavegameData_Player savegameData = readPlayerDataPreV34(src, world, fileversion);
|
||||
return new Player(savegameData);
|
||||
@@ -164,6 +165,7 @@ public final class LegacySavegameFormatReaderForPlayer {
|
||||
public String spawnPlace;
|
||||
public int availableSkillIncreases = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
public static class LegacySavegameData_Actor {
|
||||
// from Actor
|
||||
@@ -200,7 +202,7 @@ public final class LegacySavegameFormatReaderForPlayer {
|
||||
public int damageResistance;
|
||||
}
|
||||
|
||||
private static void readQuestProgressPreV13(LegacySavegameData_Player player, DataInputStream src, WorldContext world, int fileversion) throws IOException {
|
||||
public static void readQuestProgressPreV13(Player player, DataInputStream src, WorldContext world, int fileversion) throws IOException {
|
||||
final int size1 = src.readInt();
|
||||
for(int i = 0; i < size1; ++i) {
|
||||
String keyName = src.readUTF();
|
||||
@@ -245,10 +247,11 @@ public final class LegacySavegameFormatReaderForPlayer {
|
||||
}
|
||||
}
|
||||
|
||||
private static void addQuestProgress(LegacySavegameData_Player player, String questID, int progress) {
|
||||
if (!player.questProgress.containsKey(questID)) player.questProgress.put(questID, new HashSet<Integer>());
|
||||
private static void addQuestProgress(Player player, String questID, int progress) {
|
||||
player.addQuestProgress(new QuestProgress(questID, progress));
|
||||
/*if (!player.questProgress.containsKey(questID)) player.questProgress.put(questID, new HashSet<Integer>());
|
||||
else if (player.questProgress.get(questID).contains(progress)) return;
|
||||
player.questProgress.get(questID).add(progress);
|
||||
player.questProgress.get(questID).add(progress);*/
|
||||
}
|
||||
|
||||
public static void upgradeSavegame(Player player, WorldContext world, int fileversion) {
|
||||
@@ -265,7 +268,7 @@ public final class LegacySavegameFormatReaderForPlayer {
|
||||
for(SkillInfo skill : world.skills.getAllSkills()) {
|
||||
assignedSkillpoints += player.getSkillLevel(skill.id);
|
||||
}
|
||||
player.availableSkillIncreases = getExpectedNumberOfSkillpointsForLevel(player.level) - assignedSkillpoints;
|
||||
player.availableSkillIncreases = getExpectedNumberOfSkillpointsForLevel(player.getLevel()) - assignedSkillpoints;
|
||||
}
|
||||
|
||||
if (fileversion <= 21) {
|
||||
@@ -307,4 +310,21 @@ public final class LegacySavegameFormatReaderForPlayer {
|
||||
|
||||
ActorStatsController.removeConditionsFromUnequippedItem(player, world.itemTypes.getItemType(itemTypeIDWithCondition));
|
||||
}
|
||||
|
||||
public static void readCombatTraitsPreV034(DataInputStream src, int fileversion) throws IOException {
|
||||
if (fileversion < 25) return;
|
||||
if (!src.readBoolean()) return;
|
||||
|
||||
/*attackCost = */src.readInt();
|
||||
/*attackChance = */src.readInt();
|
||||
/*criticalSkill = */src.readInt();
|
||||
if (fileversion <= 20) {
|
||||
/*criticalMultiplier = */src.readInt();
|
||||
} else {
|
||||
/*criticalMultiplier = */src.readFloat();
|
||||
}
|
||||
/*damagePotential = */new Range(src, fileversion);
|
||||
/*blockChance = */src.readInt();
|
||||
/*damageResistance = */src.readInt();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@ public final class Coord {
|
||||
// ====== PARCELABLE ===================================================================
|
||||
|
||||
public Coord(DataInputStream src, int fileversion) throws IOException {
|
||||
this.readFromParcel(src, fileversion);
|
||||
}
|
||||
public void readFromParcel(DataInputStream src, int fileversion) throws IOException {
|
||||
this.x = src.readInt();
|
||||
this.y = src.readInt();
|
||||
}
|
||||
|
||||
@@ -79,6 +79,9 @@ public final class Range {
|
||||
// ====== PARCELABLE ===================================================================
|
||||
|
||||
public Range(DataInputStream src, int fileversion) throws IOException {
|
||||
this.readFromParcel(src, fileversion);
|
||||
}
|
||||
public void readFromParcel(DataInputStream src, int fileversion) throws IOException {
|
||||
this.max = src.readInt();
|
||||
this.current = src.readInt();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.gpl.rpg.AndorsTrail.view;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
import com.gpl.rpg.AndorsTrail.Dialogs;
|
||||
import com.gpl.rpg.AndorsTrail.R;
|
||||
@@ -31,7 +29,7 @@ public final class ActorConditionList extends LinearLayout {
|
||||
this.world = app.world;
|
||||
}
|
||||
|
||||
public void update(Collection<ActorCondition> conditions) {
|
||||
public void update(Iterable<ActorCondition> conditions) {
|
||||
removeAllViews();
|
||||
if (conditions == null) return;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.gpl.rpg.AndorsTrail.view;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.R;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.ActorTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Player.PlayerBaseTraits;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
@@ -18,9 +18,15 @@ public final class BaseTraitsInfoView extends TraitsInfoView {
|
||||
basetraitsinfo_max_ap = (TextView) findViewById(R.id.basetraitsinfo_max_ap);
|
||||
}
|
||||
|
||||
public void update(ActorTraits traits) {
|
||||
super.update(traits);
|
||||
|
||||
public void update(PlayerBaseTraits traits) {
|
||||
super.update(
|
||||
traits.attackCost
|
||||
,traits.attackChance
|
||||
,traits.damagePotential
|
||||
,traits.criticalSkill
|
||||
,traits.criticalMultiplier
|
||||
,traits.blockChance
|
||||
,traits.damageResistance);
|
||||
basetraitsinfo_max_hp.setText(Integer.toString(traits.maxHP));
|
||||
basetraitsinfo_max_ap.setText(Integer.toString(traits.maxAP));
|
||||
}
|
||||
|
||||
@@ -135,15 +135,15 @@ public final class CombatView extends RelativeLayout {
|
||||
monsterBar.setVisibility(View.INVISIBLE);
|
||||
currentMonster = null;
|
||||
if (selectedMonster != null) {
|
||||
attackMoveButton.setText(res.getString(R.string.combat_attack, player.combatTraits.attackCost));
|
||||
attackMoveButton.setText(res.getString(R.string.combat_attack, player.getAttackCost()));
|
||||
monsterBar.setVisibility(View.VISIBLE);
|
||||
world.tileManager.setImageViewTile(monsterInfo, selectedMonster);
|
||||
updateMonsterHealth(selectedMonster.health);
|
||||
currentMonster = selectedMonster;
|
||||
} else if (selectedMovePosition != null) {
|
||||
attackMoveButton.setText(res.getString(R.string.combat_move, player.baseTraits.moveCost));
|
||||
attackMoveButton.setText(res.getString(R.string.combat_move, player.getMoveCost()));
|
||||
} else {
|
||||
attackMoveButton.setText(res.getString(R.string.combat_attack, player.combatTraits.attackCost));
|
||||
attackMoveButton.setText(res.getString(R.string.combat_attack, player.getAttackCost()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.gpl.rpg.AndorsTrail.view;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.R;
|
||||
import com.gpl.rpg.AndorsTrail.model.CombatTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Actor;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.ActorTraits;
|
||||
import com.gpl.rpg.AndorsTrail.util.Range;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
@@ -57,58 +57,77 @@ public class TraitsInfoView extends TableLayout {
|
||||
traitsinfo_defense_damageresist = (TextView) findViewById(R.id.traitsinfo_defense_damageresist);
|
||||
}
|
||||
|
||||
public void update(Actor actor) { update(actor.combatTraits); }
|
||||
private void update(CombatTraits traits) {
|
||||
if (traits != null && traits.attackCost != 0) {
|
||||
public void update(Actor actor) {
|
||||
update(
|
||||
actor.getAttackCost()
|
||||
,actor.getAttackChance()
|
||||
,actor.getDamagePotential()
|
||||
,actor.getCriticalSkill()
|
||||
,actor.getCriticalMultiplier()
|
||||
,actor.getBlockChance()
|
||||
,actor.getDamageResistance());
|
||||
}
|
||||
|
||||
public void update(
|
||||
int attackCost
|
||||
,int attackChance
|
||||
,Range damagePotential
|
||||
,int criticalSkill
|
||||
,float criticalMultiplier
|
||||
,int blockChance
|
||||
,int damageResistance
|
||||
) {
|
||||
if (attackCost != 0) {
|
||||
traitsinfo_attack_row1.setVisibility(View.VISIBLE);
|
||||
traitsinfo_attack_cost.setText(Integer.toString(traits.attackCost));
|
||||
traitsinfo_attack_cost.setText(Integer.toString(attackCost));
|
||||
} else {
|
||||
traitsinfo_attack_row1.setVisibility(View.GONE);
|
||||
}
|
||||
if (traits != null && traits.hasAttackChanceEffect()) {
|
||||
if (attackChance != 0) {
|
||||
traitsinfo_attack_row2.setVisibility(View.VISIBLE);
|
||||
traitsinfo_attack_chance.setText(Integer.toString(traits.attackChance) + "%");
|
||||
traitsinfo_attack_chance.setText(Integer.toString(attackChance) + "%");
|
||||
} else {
|
||||
traitsinfo_attack_row2.setVisibility(View.GONE);
|
||||
}
|
||||
if (traits != null && traits.hasAttackDamageEffect()) {
|
||||
if (damagePotential.max != 0) {
|
||||
traitsinfo_attack_row3.setVisibility(View.VISIBLE);
|
||||
traitsinfo_attack_damage.setText(traits.damagePotential.toMinMaxString());
|
||||
traitsinfo_attack_damage.setText(damagePotential.toMinMaxString());
|
||||
} else {
|
||||
traitsinfo_attack_row3.setVisibility(View.GONE);
|
||||
}
|
||||
if (traits != null && traits.hasCriticalSkillEffect()) {
|
||||
if (criticalSkill != 0) {
|
||||
traitsinfo_critical_row1.setVisibility(View.VISIBLE);
|
||||
traitsinfo_criticalhit_skill.setText(Integer.toString(traits.criticalSkill));
|
||||
traitsinfo_criticalhit_skill.setText(Integer.toString(criticalSkill));
|
||||
} else {
|
||||
traitsinfo_critical_row1.setVisibility(View.GONE);
|
||||
}
|
||||
if (traits != null && traits.hasCriticalMultiplierEffect()) {
|
||||
if (criticalMultiplier != 0 && criticalMultiplier != 1) {
|
||||
traitsinfo_critical_row2.setVisibility(View.VISIBLE);
|
||||
traitsinfo_criticalhit_multiplier.setText(Float.toString(traits.criticalMultiplier));
|
||||
traitsinfo_criticalhit_multiplier.setText(Float.toString(criticalMultiplier));
|
||||
} else {
|
||||
traitsinfo_critical_row2.setVisibility(View.GONE);
|
||||
}
|
||||
if (traits != null && traits.hasCriticalAttacks()) {
|
||||
if (criticalSkill != 0 && criticalMultiplier != 0 && criticalMultiplier != 1) {
|
||||
traitsinfo_critical_row3.setVisibility(View.VISIBLE);
|
||||
traitsinfo_criticalhit_effectivechance.setText(Integer.toString(traits.getEffectiveCriticalChance()) + "%");
|
||||
traitsinfo_criticalhit_effectivechance.setText(Integer.toString(Actor.getEffectiveCriticalChance(criticalSkill)) + "%");
|
||||
} else {
|
||||
traitsinfo_critical_row3.setVisibility(View.GONE);
|
||||
}
|
||||
if (traits != null && traits.hasBlockEffect()) {
|
||||
if (blockChance != 0) {
|
||||
traitsinfo_defense_row1.setVisibility(View.VISIBLE);
|
||||
traitsinfo_defense_chance.setText(Integer.toString(traits.blockChance) + "%");
|
||||
traitsinfo_defense_chance.setText(Integer.toString(blockChance) + "%");
|
||||
} else {
|
||||
traitsinfo_defense_row1.setVisibility(View.GONE);
|
||||
}
|
||||
if (traits != null && traits.damageResistance != 0) {
|
||||
if (damageResistance != 0) {
|
||||
traitsinfo_defense_row2.setVisibility(View.VISIBLE);
|
||||
traitsinfo_defense_damageresist.setText(Integer.toString(traits.damageResistance));
|
||||
traitsinfo_defense_damageresist.setText(Integer.toString(damageResistance));
|
||||
} else {
|
||||
traitsinfo_defense_row2.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public void update(ActorTraits traits) {
|
||||
if (traits != null && traits.attackCost != 0) {
|
||||
traitsinfo_attack_row1.setVisibility(View.VISIBLE);
|
||||
@@ -159,4 +178,5 @@ public class TraitsInfoView extends TableLayout {
|
||||
traitsinfo_defense_row2.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user