mirror of
https://github.com/OMGeeky/andors-trail.git
synced 2026-02-23 15:38:29 +01:00
Merge branch 'actortraits_refactoring'
This commit is contained in:
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
>
|
||||
|
||||
<TableRow>
|
||||
<TextView android:text="@string/traitsinfo_base_max_hp" android:layout_marginRight="10sp" />
|
||||
<TextView android:id="@+id/basetraitsinfo_max_hp" />
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TextView android:text="@string/traitsinfo_base_max_ap" android:layout_marginRight="10sp" />
|
||||
<TextView android:id="@+id/basetraitsinfo_max_ap" />
|
||||
</TableRow>
|
||||
|
||||
<include layout="@layout/traitsinfoview" />
|
||||
|
||||
</merge>
|
||||
@@ -15,7 +15,9 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" >
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/heroinfo_container"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/heroinfo_title"
|
||||
@@ -32,24 +34,14 @@
|
||||
android:layout_marginBottom="@dimen/section_margin" >
|
||||
|
||||
<TableRow>
|
||||
<TextView android:layout_marginRight="10sp" android:text="@string/heroinfo_level" />
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/heroinfo_level" />
|
||||
<TextView android:id="@+id/heroinfo_level" android:text="1" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TextView android:layout_marginRight="10sp" android:text="@string/heroinfo_totalexperience" />
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/heroinfo_totalexperience" />
|
||||
<TextView android:id="@+id/heroinfo_totalexperience" android:text="1" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TextView android:layout_marginRight="10sp" android:text="@string/heroinfo_actionpoints" />
|
||||
<TextView android:id="@+id/heroinfo_ap" android:text="10/10" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TextView android:layout_marginRight="10sp" android:text="@string/actorinfo_movecost" />
|
||||
<TextView android:id="@+id/heroinfo_movecost" android:text="6" />
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
|
||||
<com.gpl.rpg.AndorsTrail.view.RangeBar
|
||||
@@ -69,38 +61,75 @@
|
||||
android:layout_marginTop="@dimen/section_margin"
|
||||
android:text="@string/actorinfo_currenttraits" />
|
||||
|
||||
<com.gpl.rpg.AndorsTrail.view.TraitsInfoView
|
||||
android:id="@+id/heroinfo_currenttraits"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView
|
||||
android:id="@+id/heroinfo_itemeffects"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/heroinfo_currentconditions_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/section_margin"
|
||||
android:text="@string/actorinfo_currentconditions" />
|
||||
|
||||
<com.gpl.rpg.AndorsTrail.view.ActorConditionList
|
||||
android:id="@+id/heroinfo_currentconditions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<TableLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/actorinfo_stats_table"
|
||||
>
|
||||
<TableRow>
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/heroinfo_actionpoints" />
|
||||
<TextView android:id="@+id/heroinfo_ap" />
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/heroinfo_reequip_cost" />
|
||||
<TextView android:id="@+id/heroinfo_reequip_cost" />
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/heroinfo_useitem_cost" />
|
||||
<TextView android:id="@+id/heroinfo_useitem_cost" />
|
||||
</TableRow>
|
||||
<include layout="@layout/traitsinfoview" />
|
||||
</TableLayout>
|
||||
|
||||
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView
|
||||
android:id="@+id/actorinfo_onhiteffects"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/actorinfo_currentconditions"
|
||||
android:id="@+id/actorinfo_currentconditions_title"
|
||||
android:layout_marginTop="@dimen/section_margin"
|
||||
/>
|
||||
<com.gpl.rpg.AndorsTrail.view.ActorConditionList
|
||||
android:id="@+id/actorinfo_currentconditions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/section_margin"
|
||||
android:text="@string/actorinfo_basetraits" />
|
||||
android:text="@string/actorinfo_basetraits"
|
||||
/>
|
||||
|
||||
<com.gpl.rpg.AndorsTrail.view.BaseTraitsInfoView
|
||||
android:id="@+id/heroinfo_basetraits"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<TableLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/heroinfo_basestats_table"
|
||||
>
|
||||
<TableRow>
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/traitsinfo_base_max_hp" />
|
||||
<TextView android:id="@+id/basetraitsinfo_max_hp" />
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/traitsinfo_base_max_ap" />
|
||||
<TextView android:id="@+id/basetraitsinfo_max_ap" />
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/heroinfo_reequip_cost" />
|
||||
<TextView android:id="@+id/heroinfo_base_reequip_cost" />
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/heroinfo_useitem_cost" />
|
||||
<TextView android:id="@+id/heroinfo_base_useitem_cost" />
|
||||
</TableRow>
|
||||
<include layout="@layout/traitsinfoview" />
|
||||
</TableLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/dialog_margin"
|
||||
android:id="@+id/monsterinfo_container"
|
||||
>
|
||||
|
||||
<TextView
|
||||
@@ -54,19 +55,20 @@
|
||||
android:layout_marginBottom="@dimen/section_margin"
|
||||
/>
|
||||
|
||||
<com.gpl.rpg.AndorsTrail.view.TraitsInfoView
|
||||
android:id="@+id/monsterinfo_currenttraits"
|
||||
<TableLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/actorinfo_immune_criticals"
|
||||
android:id="@+id/monsterinfo_immune_criticals"
|
||||
/>
|
||||
android:id="@+id/actorinfo_stats_table"
|
||||
>
|
||||
<TableRow>
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/traitsinfo_base_max_ap" />
|
||||
<TextView android:id="@+id/monsterinfo_max_ap" />
|
||||
</TableRow>
|
||||
<include layout="@layout/traitsinfoview" />
|
||||
</TableLayout>
|
||||
|
||||
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView
|
||||
android:id="@+id/monsterinfo_onhiteffects"
|
||||
android:id="@+id/actorinfo_onhiteffects"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
@@ -75,11 +77,11 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/actorinfo_currentconditions"
|
||||
android:id="@+id/monsterinfo_currentconditions_title"
|
||||
android:id="@+id/actorinfo_currentconditions_title"
|
||||
android:layout_marginTop="@dimen/section_margin"
|
||||
/>
|
||||
<com.gpl.rpg.AndorsTrail.view.ActorConditionList
|
||||
android:id="@+id/monsterinfo_currentconditions"
|
||||
android:id="@+id/actorinfo_currentconditions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
|
||||
@@ -1,56 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
>
|
||||
|
||||
<TableRow
|
||||
android:id="@+id/traitsinfo_attack_row1"
|
||||
>
|
||||
<TextView android:text="@string/traitsinfo_attack_cost" android:layout_marginRight="10sp" />
|
||||
<TableRow>
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/actorinfo_movecost" />
|
||||
<TextView android:id="@+id/traitsinfo_move_cost" />
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/traitsinfo_attack_cost" />
|
||||
<TextView android:id="@+id/traitsinfo_attack_cost" />
|
||||
</TableRow>
|
||||
<TableRow
|
||||
android:id="@+id/traitsinfo_attack_row2"
|
||||
>
|
||||
<TextView android:text="@string/traitsinfo_attack_chance" android:layout_marginRight="10sp" />
|
||||
<TableRow android:id="@+id/traitsinfo_attack_chance_row">
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/traitsinfo_attack_chance" />
|
||||
<TextView android:id="@+id/traitsinfo_attack_chance" />
|
||||
</TableRow>
|
||||
<TableRow
|
||||
android:id="@+id/traitsinfo_attack_row3"
|
||||
>
|
||||
<TextView android:text="@string/traitsinfo_attack_damage" android:layout_marginRight="10sp" />
|
||||
<TableRow android:id="@+id/traitsinfo_attack_damage_row" >
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/traitsinfo_attack_damage" />
|
||||
<TextView android:id="@+id/traitsinfo_attack_damage" />
|
||||
</TableRow>
|
||||
<TableRow
|
||||
android:id="@+id/traitsinfo_critical_row1"
|
||||
>
|
||||
<TextView android:text="@string/traitsinfo_criticalhit_skill" android:layout_marginRight="10sp" />
|
||||
<TableRow android:id="@+id/traitsinfo_criticalhit_skill_row">
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/traitsinfo_criticalhit_skill" />
|
||||
<TextView android:id="@+id/traitsinfo_criticalhit_skill" />
|
||||
</TableRow>
|
||||
<TableRow
|
||||
android:id="@+id/traitsinfo_critical_row2"
|
||||
>
|
||||
<TextView android:text="@string/traitsinfo_criticalhit_multiplier" android:layout_marginRight="10sp" />
|
||||
<TableRow android:id="@+id/traitsinfo_criticalhit_multiplier_row">
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/traitsinfo_criticalhit_multiplier" />
|
||||
<TextView android:id="@+id/traitsinfo_criticalhit_multiplier" />
|
||||
</TableRow>
|
||||
<TableRow
|
||||
android:id="@+id/traitsinfo_critical_row3"
|
||||
>
|
||||
<TextView android:text="@string/traitsinfo_criticalhit_effectivechance" android:layout_marginRight="10sp" />
|
||||
<TableRow android:id="@+id/traitsinfo_criticalhit_effectivechance_row">
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/traitsinfo_criticalhit_effectivechance" />
|
||||
<TextView android:id="@+id/traitsinfo_criticalhit_effectivechance" />
|
||||
</TableRow>
|
||||
<TableRow
|
||||
android:id="@+id/traitsinfo_defense_row1"
|
||||
>
|
||||
<TextView android:text="@string/traitsinfo_defense_chance" android:layout_marginRight="10sp" />
|
||||
<TextView android:id="@+id/traitsinfo_defense_chance" />
|
||||
<TableRow android:id="@+id/traitsinfo_block_chance_row">
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/traitsinfo_defense_chance" />
|
||||
<TextView android:id="@+id/traitsinfo_block_chance" />
|
||||
</TableRow>
|
||||
<TableRow
|
||||
android:id="@+id/traitsinfo_defense_row2"
|
||||
>
|
||||
<TextView android:text="@string/traitsinfo_defense_damageresist" android:layout_marginRight="10sp" />
|
||||
<TextView android:id="@+id/traitsinfo_defense_damageresist" />
|
||||
<TableRow android:id="@+id/traitsinfo_damageresist_row">
|
||||
<TextView style="@style/traitsinfo_label" android:text="@string/traitsinfo_defense_damageresist" />
|
||||
<TextView android:id="@+id/traitsinfo_damageresist" />
|
||||
</TableRow>
|
||||
</merge>
|
||||
<TableRow android:id="@+id/traitsinfo_is_immune_to_critical_hits_row">
|
||||
<TextView android:text="@string/actorinfo_immune_criticals" android:layout_span="2" />
|
||||
</TableRow>
|
||||
</merge>
|
||||
@@ -559,5 +559,10 @@
|
||||
<string name="preferences_dialog_overwrite_savegame_title">Confirm overwriting savegames</string>
|
||||
<string name="preferences_dialog_overwrite_savegame">Gives a question about whether you want to overwrite when saving to a savegame slot that already contains a savegame.</string>
|
||||
|
||||
|
||||
<!-- =========================================== -->
|
||||
<!-- Added in v0.7.0 -->
|
||||
|
||||
<string name="heroinfo_reequip_cost">Re-equip cost (AP):</string>
|
||||
<string name="heroinfo_useitem_cost">Use item cost (AP):</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -34,4 +34,8 @@
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
</style>
|
||||
|
||||
<style name="traitsinfo_label" parent="android:Widget.TextView">
|
||||
<item name="android:layout_marginRight">10sp</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -106,7 +106,7 @@ public final class Savegames {
|
||||
public static void saveWorld(WorldContext world, OutputStream outStream, String displayInfo) throws IOException {
|
||||
DataOutputStream dest = new DataOutputStream(outStream);
|
||||
final int flags = 0;
|
||||
FileHeader.writeToParcel(dest, world.model.player.actorTraits.name, displayInfo);
|
||||
FileHeader.writeToParcel(dest, world.model.player.getName(), displayInfo);
|
||||
world.maps.writeToParcel(dest, flags);
|
||||
world.model.writeToParcel(dest, flags);
|
||||
dest.close();
|
||||
@@ -127,7 +127,7 @@ public final class Savegames {
|
||||
}
|
||||
|
||||
private static void onWorldLoaded(WorldContext world) {
|
||||
ActorStatsController.recalculatePlayerCombatTraits(world.model.player);
|
||||
ActorStatsController.recalculatePlayerStats(world.model.player);
|
||||
Controller.resetMapsNotRecentlyVisited(world);
|
||||
MovementController.moveBlockedActors(world);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -343,14 +343,14 @@ public final class ConversationActivity extends Activity implements OnKeyListene
|
||||
ConversationStatement s = new ConversationStatement();
|
||||
if (displayActors) {
|
||||
assert(actor != null);
|
||||
s.iconID = actor.actorTraits.iconID;
|
||||
s.actorName = actor.actorTraits.name;
|
||||
s.iconID = actor.iconID;
|
||||
s.actorName = actor.getName();
|
||||
} else {
|
||||
s.iconID = ConversationStatement.NO_ICON;
|
||||
}
|
||||
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);
|
||||
}
|
||||
@@ -127,9 +127,9 @@ public final class DebugInterface {
|
||||
,new DebugButton("hp", new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View arg0) {
|
||||
world.model.player.actorTraits.maxHP = 200;
|
||||
world.model.player.health.max = world.model.player.actorTraits.maxHP;
|
||||
world.model.player.health.setMax();
|
||||
world.model.player.baseTraits.maxHP = 200;
|
||||
world.model.player.health.max = world.model.player.baseTraits.maxHP;
|
||||
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);
|
||||
|
||||
@@ -10,8 +10,6 @@ import com.gpl.rpg.AndorsTrail.model.actor.Player;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.Inventory;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnUse;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
|
||||
import com.gpl.rpg.AndorsTrail.view.ActorConditionList;
|
||||
import com.gpl.rpg.AndorsTrail.view.BaseTraitsInfoView;
|
||||
import com.gpl.rpg.AndorsTrail.view.ItemEffectsView;
|
||||
import com.gpl.rpg.AndorsTrail.view.RangeBar;
|
||||
import com.gpl.rpg.AndorsTrail.view.TraitsInfoView;
|
||||
@@ -21,7 +19,9 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
public final class HeroinfoActivity_Stats extends Activity {
|
||||
@@ -31,16 +31,19 @@ public final class HeroinfoActivity_Stats extends Activity {
|
||||
|
||||
private Button levelUpButton;
|
||||
private TextView heroinfo_ap;
|
||||
private TextView heroinfo_movecost;
|
||||
private TraitsInfoView heroinfo_currenttraits;
|
||||
private ItemEffectsView heroinfo_itemeffects;
|
||||
private TextView heroinfo_currentconditions_title;
|
||||
private ActorConditionList heroinfo_currentconditions;
|
||||
private TextView heroinfo_reequip_cost;
|
||||
private TextView heroinfo_useitem_cost;
|
||||
private TextView heroinfo_level;
|
||||
private TextView heroinfo_totalexperience;
|
||||
private TextView basetraitsinfo_max_hp;
|
||||
private TextView basetraitsinfo_max_ap;
|
||||
private TextView heroinfo_base_reequip_cost;
|
||||
private TextView heroinfo_base_useitem_cost;
|
||||
private RangeBar rangebar_hp;
|
||||
private RangeBar rangebar_exp;
|
||||
private BaseTraitsInfoView heroinfo_basetraits;
|
||||
private ItemEffectsView actorinfo_onhiteffects;
|
||||
private TableLayout heroinfo_basestats_table;
|
||||
private ViewGroup heroinfo_container;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -53,17 +56,22 @@ public final class HeroinfoActivity_Stats extends Activity {
|
||||
setContentView(R.layout.heroinfo_stats);
|
||||
|
||||
TextView tv = (TextView) findViewById(R.id.heroinfo_title);
|
||||
tv.setText(player.actorTraits.name);
|
||||
tv.setText(player.getName());
|
||||
world.tileManager.setImageViewTile(tv, player);
|
||||
|
||||
heroinfo_container = (ViewGroup) findViewById(R.id.heroinfo_container);
|
||||
heroinfo_ap = (TextView) findViewById(R.id.heroinfo_ap);
|
||||
heroinfo_movecost = (TextView) findViewById(R.id.heroinfo_movecost);
|
||||
heroinfo_currenttraits = (TraitsInfoView) findViewById(R.id.heroinfo_currenttraits);
|
||||
heroinfo_itemeffects = (ItemEffectsView) findViewById(R.id.heroinfo_itemeffects);
|
||||
heroinfo_currentconditions_title = (TextView) findViewById(R.id.heroinfo_currentconditions_title);
|
||||
heroinfo_currentconditions = (ActorConditionList) findViewById(R.id.heroinfo_currentconditions);
|
||||
heroinfo_reequip_cost = (TextView) findViewById(R.id.heroinfo_reequip_cost);
|
||||
heroinfo_useitem_cost = (TextView) findViewById(R.id.heroinfo_useitem_cost);
|
||||
basetraitsinfo_max_hp = (TextView) findViewById(R.id.basetraitsinfo_max_hp);
|
||||
basetraitsinfo_max_ap = (TextView) findViewById(R.id.basetraitsinfo_max_ap);
|
||||
heroinfo_base_reequip_cost = (TextView) findViewById(R.id.heroinfo_base_reequip_cost);
|
||||
heroinfo_base_useitem_cost = (TextView) findViewById(R.id.heroinfo_base_useitem_cost);
|
||||
heroinfo_level = (TextView) findViewById(R.id.heroinfo_level);
|
||||
heroinfo_totalexperience = (TextView) findViewById(R.id.heroinfo_totalexperience);
|
||||
|
||||
actorinfo_onhiteffects = (ItemEffectsView) findViewById(R.id.actorinfo_onhiteffects);
|
||||
heroinfo_basestats_table = (TableLayout) findViewById(R.id.heroinfo_basestats_table);
|
||||
|
||||
rangebar_hp = (RangeBar) findViewById(R.id.heroinfo_healthbar);
|
||||
rangebar_hp.init(R.drawable.ui_progress_health, R.string.status_hp);
|
||||
rangebar_exp = (RangeBar) findViewById(R.id.heroinfo_expbar);
|
||||
@@ -81,8 +89,6 @@ public final class HeroinfoActivity_Stats extends Activity {
|
||||
levelUpButton.setEnabled(false);
|
||||
}
|
||||
});
|
||||
|
||||
heroinfo_basetraits = (BaseTraitsInfoView) findViewById(R.id.heroinfo_basetraits);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -90,7 +96,6 @@ public final class HeroinfoActivity_Stats extends Activity {
|
||||
super.onResume();
|
||||
updateTraits();
|
||||
updateLevelup();
|
||||
updateConditions();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -105,17 +110,35 @@ public final class HeroinfoActivity_Stats extends Activity {
|
||||
private void updateLevelup() {
|
||||
levelUpButton.setEnabled(player.canLevelup());
|
||||
}
|
||||
|
||||
|
||||
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.actorTraits.moveCost));
|
||||
heroinfo_reequip_cost.setText(Integer.toString(player.getReequipCost()));
|
||||
heroinfo_useitem_cost.setText(Integer.toString(player.getUseItemCost()));
|
||||
basetraitsinfo_max_hp.setText(Integer.toString(player.baseTraits.maxHP));
|
||||
basetraitsinfo_max_ap.setText(Integer.toString(player.baseTraits.maxAP));
|
||||
heroinfo_base_reequip_cost.setText(Integer.toString(player.baseTraits.reequipCost));
|
||||
heroinfo_base_useitem_cost.setText(Integer.toString(player.baseTraits.useItemCost));
|
||||
rangebar_hp.update(player.health);
|
||||
rangebar_exp.update(player.levelExperience);
|
||||
|
||||
heroinfo_currenttraits.update(player);
|
||||
ArrayList<ItemTraits_OnUse> effects_hit = new ArrayList<ItemTraits_OnUse>();
|
||||
TraitsInfoView.update(heroinfo_container, player);
|
||||
TraitsInfoView.updateTraitsTable(
|
||||
heroinfo_basestats_table
|
||||
, player.baseTraits.moveCost
|
||||
, player.baseTraits.attackCost
|
||||
, player.baseTraits.attackChance
|
||||
, player.baseTraits.damagePotential
|
||||
, player.baseTraits.criticalSkill
|
||||
, player.baseTraits.criticalMultiplier
|
||||
, player.baseTraits.blockChance
|
||||
, player.baseTraits.damageResistance
|
||||
, false
|
||||
);
|
||||
|
||||
ArrayList<ItemTraits_OnUse> effects_hit = new ArrayList<ItemTraits_OnUse>();
|
||||
ArrayList<ItemTraits_OnUse> effects_kill = new ArrayList<ItemTraits_OnUse>();
|
||||
for (int i = 0; i < Inventory.NUM_WORN_SLOTS; ++i) {
|
||||
ItemType type = player.inventory.wear[i];
|
||||
@@ -125,18 +148,6 @@ public final class HeroinfoActivity_Stats extends Activity {
|
||||
}
|
||||
if (effects_hit.isEmpty()) effects_hit = null;
|
||||
if (effects_kill.isEmpty()) effects_kill = null;
|
||||
heroinfo_itemeffects.update(null, null, effects_hit, effects_kill, false);
|
||||
heroinfo_basetraits.update(player.actorTraits);
|
||||
actorinfo_onhiteffects.update(null, null, effects_hit, effects_kill, false);
|
||||
}
|
||||
|
||||
private void updateConditions() {
|
||||
if (player.conditions.isEmpty()) {
|
||||
heroinfo_currentconditions_title.setVisibility(View.GONE);
|
||||
heroinfo_currentconditions.setVisibility(View.GONE);
|
||||
} else {
|
||||
heroinfo_currentconditions_title.setVisibility(View.VISIBLE);
|
||||
heroinfo_currentconditions.setVisibility(View.VISIBLE);
|
||||
heroinfo_currentconditions.update(player.conditions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -118,14 +118,14 @@ public final class LevelUpActivity extends Activity {
|
||||
hpIncrease = Constants.LEVELUP_EFFECT_HEALTH;
|
||||
break;
|
||||
case SELECT_ATK_CH:
|
||||
player.actorTraits.baseCombatTraits.attackChance += Constants.LEVELUP_EFFECT_ATK_CH;
|
||||
player.baseTraits.attackChance += Constants.LEVELUP_EFFECT_ATK_CH;
|
||||
break;
|
||||
case SELECT_ATK_DMG:
|
||||
player.actorTraits.baseCombatTraits.damagePotential.max += Constants.LEVELUP_EFFECT_ATK_DMG;
|
||||
player.actorTraits.baseCombatTraits.damagePotential.current += Constants.LEVELUP_EFFECT_ATK_DMG;
|
||||
player.baseTraits.damagePotential.max += Constants.LEVELUP_EFFECT_ATK_DMG;
|
||||
player.baseTraits.damagePotential.current += Constants.LEVELUP_EFFECT_ATK_DMG;
|
||||
break;
|
||||
case SELECT_DEF_CH:
|
||||
player.actorTraits.baseCombatTraits.blockChance += Constants.LEVELUP_EFFECT_DEF_CH;
|
||||
player.baseTraits.blockChance += Constants.LEVELUP_EFFECT_DEF_CH;
|
||||
break;
|
||||
}
|
||||
if (player.nextLevelAddsNewSkillpoint()) {
|
||||
@@ -135,10 +135,9 @@ public final class LevelUpActivity extends Activity {
|
||||
|
||||
hpIncrease += player.getSkillLevel(SkillCollection.SKILL_FORTITUDE) * SkillCollection.PER_SKILLPOINT_INCREASE_FORTITUDE_HEALTH;
|
||||
player.health.max += hpIncrease;
|
||||
player.actorTraits.maxHP += hpIncrease;
|
||||
player.baseTraits.maxHP += hpIncrease;
|
||||
player.health.current += hpIncrease;
|
||||
|
||||
player.recalculateLevelExperience();
|
||||
ActorStatsController.recalculatePlayerCombatTraits(player);
|
||||
ActorStatsController.recalculatePlayerStats(player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public final class LoadSaveActivity extends Activity implements OnClickListener
|
||||
return null;
|
||||
}
|
||||
|
||||
final String currentPlayerName = model.player.actorTraits.name;
|
||||
final String currentPlayerName = model.player.getName();
|
||||
final FileHeader header = Savegames.quickload(this, slot);
|
||||
if (header == null) return null;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -37,7 +37,7 @@ public final class MonsterEncounterActivity extends Activity {
|
||||
CharSequence difficulty = getText(MonsterInfoActivity.getMonsterDifficultyResource(world, monster));
|
||||
|
||||
TextView tv = (TextView) findViewById(R.id.monsterencounter_title);
|
||||
tv.setText(monster.actorTraits.name);
|
||||
tv.setText(monster.getName());
|
||||
world.tileManager.setImageViewTile(tv, monster);
|
||||
|
||||
tv = (TextView) findViewById(R.id.monsterencounter_description);
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
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;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.controller.CombatController;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Monster;
|
||||
import com.gpl.rpg.AndorsTrail.view.ActorConditionList;
|
||||
import com.gpl.rpg.AndorsTrail.view.ItemEffectsView;
|
||||
import com.gpl.rpg.AndorsTrail.view.RangeBar;
|
||||
import com.gpl.rpg.AndorsTrail.view.TraitsInfoView;
|
||||
@@ -16,6 +13,7 @@ import com.gpl.rpg.AndorsTrail.view.TraitsInfoView;
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
@@ -23,16 +21,16 @@ import android.widget.TextView;
|
||||
|
||||
public final class MonsterInfoActivity extends Activity {
|
||||
|
||||
private TextView monsterinfo_title;
|
||||
private TextView monsterinfo_difficulty;
|
||||
private TraitsInfoView monsterinfo_currenttraits;
|
||||
private ItemEffectsView monsterinfo_onhiteffects;
|
||||
private TextView monsterinfo_currentconditions_title;
|
||||
private TextView monsterinfo_immune_criticals;
|
||||
private ActorConditionList monsterinfo_currentconditions;
|
||||
private RangeBar hp;
|
||||
private WorldContext world;
|
||||
|
||||
private TextView monsterinfo_title;
|
||||
private TextView monsterinfo_difficulty;
|
||||
private ItemEffectsView monsterinfo_onhiteffects;
|
||||
private RangeBar hp;
|
||||
private ViewGroup monsterinfo_container;
|
||||
private TextView monsterinfo_max_ap;
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -45,7 +43,7 @@ public final class MonsterInfoActivity extends Activity {
|
||||
|
||||
monsterinfo_title = (TextView) findViewById(R.id.monsterinfo_title);
|
||||
monsterinfo_difficulty = (TextView) findViewById(R.id.monsterinfo_difficulty);
|
||||
monsterinfo_immune_criticals = (TextView) findViewById(R.id.monsterinfo_immune_criticals);
|
||||
monsterinfo_max_ap = (TextView) findViewById(R.id.monsterinfo_max_ap);
|
||||
|
||||
Button b = (Button) findViewById(R.id.monsterinfo_close);
|
||||
b.setOnClickListener(new OnClickListener() {
|
||||
@@ -55,12 +53,10 @@ public final class MonsterInfoActivity extends Activity {
|
||||
}
|
||||
});
|
||||
|
||||
monsterinfo_currenttraits = (TraitsInfoView) findViewById(R.id.monsterinfo_currenttraits);
|
||||
monsterinfo_onhiteffects = (ItemEffectsView) findViewById(R.id.monsterinfo_onhiteffects);
|
||||
monsterinfo_currentconditions_title = (TextView) findViewById(R.id.monsterinfo_currentconditions_title);
|
||||
monsterinfo_currentconditions = (ActorConditionList) findViewById(R.id.monsterinfo_currentconditions);
|
||||
monsterinfo_onhiteffects = (ItemEffectsView) findViewById(R.id.actorinfo_onhiteffects);
|
||||
hp = (RangeBar) findViewById(R.id.monsterinfo_healthbar);
|
||||
hp.init(R.drawable.ui_progress_health, R.string.status_hp);
|
||||
monsterinfo_container = (ViewGroup) findViewById(R.id.monsterinfo_container);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -75,25 +71,24 @@ public final class MonsterInfoActivity extends Activity {
|
||||
|
||||
updateTitle(monster);
|
||||
updateTraits(monster);
|
||||
updateConditions(monster);
|
||||
}
|
||||
|
||||
private void updateTitle(Monster monster) {
|
||||
monsterinfo_title.setText(monster.actorTraits.name);
|
||||
monsterinfo_title.setText(monster.getName());
|
||||
world.tileManager.setImageViewTile(monsterinfo_title, monster);
|
||||
monsterinfo_difficulty.setText(getMonsterDifficultyResource(world, monster));
|
||||
}
|
||||
|
||||
private void updateTraits(Monster monster) {
|
||||
monsterinfo_currenttraits.update(monster);
|
||||
TraitsInfoView.update(monsterinfo_container, monster);
|
||||
monsterinfo_onhiteffects.update(
|
||||
null,
|
||||
null,
|
||||
monster.actorTraits.onHitEffects == null ? null : Arrays.asList(monster.actorTraits.onHitEffects),
|
||||
monster.getOnHitEffectsAsList(),
|
||||
null,
|
||||
false);
|
||||
hp.update(monster.health);
|
||||
monsterinfo_immune_criticals.setVisibility(monster.isImmuneToCriticalHits ? View.VISIBLE : View.GONE);
|
||||
monsterinfo_max_ap.setText(Integer.toString(monster.ap.max));
|
||||
}
|
||||
|
||||
public static int getMonsterDifficultyResource(WorldContext world, Monster monster) {
|
||||
@@ -105,15 +100,4 @@ public final class MonsterInfoActivity extends Activity {
|
||||
else if (difficulty == 0) return R.string.monster_difficulty_impossible;
|
||||
else return R.string.monster_difficulty_veryhard;
|
||||
}
|
||||
|
||||
private void updateConditions(Monster monster) {
|
||||
if (monster.conditions.isEmpty()) {
|
||||
monsterinfo_currentconditions_title.setVisibility(View.GONE);
|
||||
monsterinfo_currentconditions.setVisibility(View.GONE);
|
||||
} else {
|
||||
monsterinfo_currentconditions_title.setVisibility(View.VISIBLE);
|
||||
monsterinfo_currentconditions.setVisibility(View.VISIBLE);
|
||||
monsterinfo_currentconditions.update(monster.conditions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -4,11 +4,9 @@ import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
import com.gpl.rpg.AndorsTrail.R;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.controller.SkillController;
|
||||
import com.gpl.rpg.AndorsTrail.model.CombatTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.SkillInfo;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.SkillInfo.SkillLevelRequirement;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.ActorTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Player;
|
||||
|
||||
import android.app.Activity;
|
||||
@@ -194,9 +192,9 @@ public final class SkillInfoActivity extends Activity {
|
||||
|
||||
private static int getRequirementActorStatsResourceID(int statID) {
|
||||
switch (statID) {
|
||||
case ActorTraits.STAT_ACTOR_MAX_HP: return R.string.actorinfo_health;
|
||||
case ActorTraits.STAT_ACTOR_MAX_AP: return R.string.heroinfo_actionpoints;
|
||||
case ActorTraits.STAT_ACTOR_MOVECOST: return R.string.actorinfo_movecost;
|
||||
case Player.STAT_ACTOR_MAX_HP: return R.string.actorinfo_health;
|
||||
case Player.STAT_ACTOR_MAX_AP: return R.string.heroinfo_actionpoints;
|
||||
case Player.STAT_ACTOR_MOVECOST: return R.string.actorinfo_movecost;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@@ -204,14 +202,14 @@ public final class SkillInfoActivity extends Activity {
|
||||
|
||||
private static int getRequirementCombatStatsResourceID(int statID) {
|
||||
switch (statID) {
|
||||
case CombatTraits.STAT_COMBAT_ATTACK_COST: return R.string.traitsinfo_attack_cost;
|
||||
case CombatTraits.STAT_COMBAT_ATTACK_CHANCE: return R.string.traitsinfo_attack_chance;
|
||||
case CombatTraits.STAT_COMBAT_CRITICAL_SKILL: return R.string.traitsinfo_criticalhit_skill;
|
||||
case CombatTraits.STAT_COMBAT_CRITICAL_MULTIPLIER: return R.string.traitsinfo_criticalhit_multiplier;
|
||||
case CombatTraits.STAT_COMBAT_DAMAGE_POTENTIAL_MIN: return R.string.traitsinfo_attack_damage;
|
||||
case CombatTraits.STAT_COMBAT_DAMAGE_POTENTIAL_MAX: return R.string.traitsinfo_attack_damage;
|
||||
case CombatTraits.STAT_COMBAT_BLOCK_CHANCE: return R.string.traitsinfo_defense_chance;
|
||||
case CombatTraits.STAT_COMBAT_DAMAGE_RESISTANCE: return R.string.traitsinfo_defense_damageresist;
|
||||
case Player.STAT_COMBAT_ATTACK_COST: return R.string.traitsinfo_attack_cost;
|
||||
case Player.STAT_COMBAT_ATTACK_CHANCE: return R.string.traitsinfo_attack_chance;
|
||||
case Player.STAT_COMBAT_CRITICAL_SKILL: return R.string.traitsinfo_criticalhit_skill;
|
||||
case Player.STAT_COMBAT_CRITICAL_MULTIPLIER: return R.string.traitsinfo_criticalhit_multiplier;
|
||||
case Player.STAT_COMBAT_DAMAGE_POTENTIAL_MIN: return R.string.traitsinfo_attack_damage;
|
||||
case Player.STAT_COMBAT_DAMAGE_POTENTIAL_MAX: return R.string.traitsinfo_attack_damage;
|
||||
case Player.STAT_COMBAT_BLOCK_CHANCE: return R.string.traitsinfo_defense_chance;
|
||||
case Player.STAT_COMBAT_DAMAGE_RESISTANCE: return R.string.traitsinfo_defense_damageresist;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import java.util.ArrayList;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.VisualEffectCollection;
|
||||
import com.gpl.rpg.AndorsTrail.context.ViewContext;
|
||||
import com.gpl.rpg.AndorsTrail.model.CombatTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionEffect;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionType;
|
||||
@@ -167,37 +166,44 @@ 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.actorTraits.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.actorTraits.moveCost <= 0) actor.actorTraits.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 recalculatePlayerStats(Player player) {
|
||||
player.resetStatsToBaseTraits();
|
||||
player.recalculateLevelExperience();
|
||||
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) recalculatePlayerStats((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);
|
||||
recalculatePlayerStats(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,8 +317,10 @@ public class ActorStatsController {
|
||||
}
|
||||
}
|
||||
}
|
||||
VisualEffect effectToStart = applyStatsModifierEffect(source, effect, 1, null);
|
||||
startVisualEffect(source, effectToStart);
|
||||
if (effect.changedStats != null) {
|
||||
VisualEffect effectToStart = applyStatsModifierEffect(source, effect.changedStats, 1, null);
|
||||
startVisualEffect(source, effectToStart);
|
||||
}
|
||||
}
|
||||
|
||||
private static void rollForConditionEffect(Actor actor, ActorConditionEffect conditionEffect) {
|
||||
@@ -396,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;
|
||||
|
||||
@@ -179,7 +178,7 @@ public final class CombatController implements VisualEffectCompletedCallback {
|
||||
if (attack.isHit) {
|
||||
String msg;
|
||||
|
||||
final String monsterName = target.actorTraits.name;
|
||||
final String monsterName = target.getName();
|
||||
if (attack.isCriticalHit) {
|
||||
msg = r.getString(R.string.combat_result_herohitcritical, monsterName, attack.damage);
|
||||
} else {
|
||||
@@ -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.actorTraits.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.actorTraits.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,14 +331,14 @@ 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();
|
||||
AttackResult attack = monsterAttacks(model, currentActiveMonster);
|
||||
this.lastAttackResult = attack;
|
||||
|
||||
String monsterName = currentActiveMonster.actorTraits.name;
|
||||
String monsterName = currentActiveMonster.getName();
|
||||
if (attack.isHit) {
|
||||
if (attack.isCriticalHit) {
|
||||
message(r.getString(R.string.combat_result_monsterhitcritical, monsterName, attack.damage));
|
||||
@@ -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.actorTraits.maxHP / 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.actorTraits.onHitEffects == null) return;
|
||||
ItemTraits_OnUse[] onHitEffects = attacker.getOnHitEffects();
|
||||
if (onHitEffects == null) return;
|
||||
|
||||
for (ItemTraits_OnUse e : attacker.actorTraits.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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,12 +78,11 @@ public final class Controller {
|
||||
public static void playerRested(final WorldContext world, MapObject area) {
|
||||
final Player player = world.model.player;
|
||||
ActorStatsController.removeAllTemporaryConditions(player);
|
||||
ActorStatsController.recalculatePlayerCombatTraits(player);
|
||||
ActorStatsController.recalculatePlayerStats(player);
|
||||
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();
|
||||
|
||||
@@ -100,6 +100,6 @@ public final class ConversationController {
|
||||
public static String getDisplayMessage(Phrase phrase, Player player) { return replacePlayerName(phrase.message, player); }
|
||||
public static String getDisplayMessage(Reply reply, Player player) { return replacePlayerName(reply.text, player); }
|
||||
public static String replacePlayerName(String s, Player player) {
|
||||
return s.replace(Constants.PLACEHOLDER_PLAYERNAME, player.actorTraits.name);
|
||||
return s.replace(Constants.PLACEHOLDER_PLAYERNAME, player.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import com.gpl.rpg.AndorsTrail.Dialogs;
|
||||
import com.gpl.rpg.AndorsTrail.context.ViewContext;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.model.ModelContainer;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionEffect;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.traits.AbilityModifierTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Player;
|
||||
@@ -40,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;
|
||||
@@ -54,7 +53,7 @@ public final class ItemController {
|
||||
|
||||
player.inventory.wear[slot] = type;
|
||||
ActorStatsController.addConditionsFromEquippedItem(player, type);
|
||||
ActorStatsController.recalculatePlayerCombatTraits(player);
|
||||
ActorStatsController.recalculatePlayerStats(player);
|
||||
}
|
||||
|
||||
public void unequipSlot(ItemType type, int slot) {
|
||||
@@ -63,11 +62,11 @@ 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);
|
||||
ActorStatsController.recalculatePlayerCombatTraits(player);
|
||||
ActorStatsController.recalculatePlayerStats(player);
|
||||
}
|
||||
|
||||
private static void unequipSlot(Player player, int slot) {
|
||||
@@ -82,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;
|
||||
@@ -102,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);
|
||||
@@ -154,9 +153,9 @@ public final class ItemController {
|
||||
if (effects != null) {
|
||||
ItemTraits_OnUse[] effects_ = new ItemTraits_OnUse[effects.size()];
|
||||
effects_ = effects.toArray(effects_);
|
||||
player.actorTraits.onHitEffects = effects_;
|
||||
player.onHitEffects = effects_;
|
||||
} else {
|
||||
player.actorTraits.onHitEffects = null;
|
||||
player.onHitEffects = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,22 +324,4 @@ public final class ItemController {
|
||||
model.player.inventory.quickitem[quickSlotId] = itemType;
|
||||
view.mainActivity.updateStatus();
|
||||
}
|
||||
|
||||
public static void correctActorConditionsFromItemsPre0611b1(Player player, String conditionTypeID, WorldContext world, String itemTypeIDWithCondition) {
|
||||
if (!player.hasCondition(conditionTypeID)) return;
|
||||
boolean hasItemWithCondition = false;
|
||||
for (ItemType t : player.inventory.wear) {
|
||||
if (t == null) continue;
|
||||
if (t.effects_equip == null) continue;
|
||||
if (t.effects_equip.addedConditions == null) continue;
|
||||
for(ActorConditionEffect e : t.effects_equip.addedConditions) {
|
||||
if (!e.conditionType.conditionTypeID.equals(conditionTypeID)) continue;
|
||||
hasItemWithCondition = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasItemWithCondition) return;
|
||||
|
||||
ActorStatsController.removeConditionsFromUnequippedItem(player, world.itemTypes.getItemType(itemTypeIDWithCondition));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
@@ -257,7 +257,7 @@ public final class MovementController implements TimedMessageTask.Callback {
|
||||
for (MonsterSpawnArea a : map.spawnAreas) {
|
||||
for (Monster m : a.monsters) {
|
||||
if (!map.isWalkable(m.rectPosition)) {
|
||||
Coord p = map.getRandomFreePosition(a.area, m.actorTraits.tileSize, playerPosition);
|
||||
Coord p = map.getRandomFreePosition(a.area, m.tileSize, playerPosition);
|
||||
if (p == null) continue;
|
||||
m.position.set(p);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.gpl.rpg.AndorsTrail.controller;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.model.AttackResult;
|
||||
import com.gpl.rpg.AndorsTrail.model.CombatTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionEffect;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionType;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection;
|
||||
@@ -17,17 +16,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 +143,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));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
package com.gpl.rpg.AndorsTrail.model;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import android.util.FloatMath;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.util.Range;
|
||||
|
||||
public class CombatTraits {
|
||||
public static final int STAT_COMBAT_ATTACK_COST = 0;
|
||||
public static final int STAT_COMBAT_ATTACK_CHANCE = 1;
|
||||
public static final int STAT_COMBAT_CRITICAL_SKILL = 2;
|
||||
public static final int STAT_COMBAT_CRITICAL_MULTIPLIER = 3;
|
||||
public static final int STAT_COMBAT_DAMAGE_POTENTIAL_MIN = 4;
|
||||
public static final int STAT_COMBAT_DAMAGE_POTENTIAL_MAX = 5;
|
||||
public static final int STAT_COMBAT_BLOCK_CHANCE = 6;
|
||||
public static final int STAT_COMBAT_DAMAGE_RESISTANCE = 7;
|
||||
|
||||
public int attackCost;
|
||||
|
||||
public int attackChance;
|
||||
public int criticalSkill;
|
||||
public float criticalMultiplier;
|
||||
public final Range damagePotential;
|
||||
|
||||
public int blockChance;
|
||||
public int damageResistance;
|
||||
|
||||
public CombatTraits() {
|
||||
this.damagePotential = new Range();
|
||||
}
|
||||
public CombatTraits(CombatTraits copy) {
|
||||
this();
|
||||
set(copy);
|
||||
}
|
||||
public void set(CombatTraits copy) {
|
||||
if (copy == null) return;
|
||||
this.attackCost = copy.attackCost;
|
||||
this.attackChance = copy.attackChance;
|
||||
this.criticalSkill = copy.criticalSkill;
|
||||
this.criticalMultiplier = copy.criticalMultiplier;
|
||||
this.damagePotential.set(copy.damagePotential);
|
||||
this.blockChance = copy.blockChance;
|
||||
this.damageResistance = copy.damageResistance;
|
||||
}
|
||||
|
||||
public boolean equals(CombatTraits other) {
|
||||
if (other == null) return isZero();
|
||||
return
|
||||
this.attackCost == other.attackCost
|
||||
&& this.attackChance == other.attackChance
|
||||
&& this.criticalSkill == other.criticalSkill
|
||||
&& this.criticalMultiplier == other.criticalMultiplier
|
||||
&& this.damagePotential.equals(other.damagePotential)
|
||||
&& this.blockChance == other.blockChance
|
||||
&& this.damageResistance == other.damageResistance;
|
||||
}
|
||||
|
||||
private boolean isZero() {
|
||||
return
|
||||
this.attackCost == 0
|
||||
&& this.attackChance == 0
|
||||
&& this.criticalSkill == 0
|
||||
&& this.criticalMultiplier == 0
|
||||
&& this.damagePotential.current == 0
|
||||
&& this.damagePotential.max == 0
|
||||
&& this.blockChance == 0
|
||||
&& this.damageResistance == 0;
|
||||
}
|
||||
|
||||
public boolean hasAttackChanceEffect() { return attackChance != 0; }
|
||||
public boolean hasAttackDamageEffect() { return damagePotential.max != 0; }
|
||||
public boolean hasBlockEffect() { return blockChance != 0; }
|
||||
public boolean hasCriticalSkillEffect() { return criticalSkill != 0; }
|
||||
public boolean hasCriticalMultiplierEffect() { return criticalMultiplier != 0 && criticalMultiplier != 1; }
|
||||
public boolean hasCriticalAttacks() { return hasCriticalSkillEffect() && hasCriticalMultiplierEffect(); }
|
||||
|
||||
public int getEffectiveCriticalChance() {
|
||||
if (criticalSkill <= 0) return 0;
|
||||
int v = (int) (-5 + 2 * FloatMath.sqrt(5*criticalSkill));
|
||||
if (v < 0) return 0;
|
||||
return v;
|
||||
}
|
||||
|
||||
public int getAttacksPerTurn(final int maxAP) {
|
||||
return (int) Math.floor(maxAP / attackCost);
|
||||
}
|
||||
|
||||
public int getCombatStats(int statID) {
|
||||
switch (statID) {
|
||||
case STAT_COMBAT_ATTACK_COST: return attackCost;
|
||||
case STAT_COMBAT_ATTACK_CHANCE: return attackChance;
|
||||
case STAT_COMBAT_CRITICAL_SKILL: return criticalSkill;
|
||||
case STAT_COMBAT_CRITICAL_MULTIPLIER: return (int) FloatMath.floor(criticalMultiplier);
|
||||
case STAT_COMBAT_DAMAGE_POTENTIAL_MIN: return damagePotential.current;
|
||||
case STAT_COMBAT_DAMAGE_POTENTIAL_MAX: return damagePotential.max;
|
||||
case STAT_COMBAT_BLOCK_CHANCE: return blockChance;
|
||||
case STAT_COMBAT_DAMAGE_RESISTANCE: return damageResistance;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ====== PARCELABLE ===================================================================
|
||||
|
||||
public CombatTraits(DataInputStream src, int fileversion) throws IOException {
|
||||
this.attackCost = src.readInt();
|
||||
this.attackChance = src.readInt();
|
||||
this.criticalSkill = src.readInt();
|
||||
if (fileversion <= 20) {
|
||||
this.criticalMultiplier = src.readInt();
|
||||
} else {
|
||||
this.criticalMultiplier = src.readFloat();
|
||||
}
|
||||
this.damagePotential = new Range(src, fileversion);
|
||||
this.blockChance = src.readInt();
|
||||
this.damageResistance = src.readInt();
|
||||
}
|
||||
|
||||
public void writeToParcel(DataOutputStream dest, int flags) throws IOException {
|
||||
dest.writeInt(attackCost);
|
||||
dest.writeInt(attackChance);
|
||||
dest.writeInt(criticalSkill);
|
||||
dest.writeFloat(criticalMultiplier);
|
||||
damagePotential.writeToParcel(dest, flags);
|
||||
dest.writeInt(blockChance);
|
||||
dest.writeInt(damageResistance);
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ public final class ModelContainer {
|
||||
// ====== PARCELABLE ===================================================================
|
||||
|
||||
public ModelContainer(DataInputStream src, WorldContext world, int fileversion) throws IOException {
|
||||
this.player = new Player(src, world, fileversion);
|
||||
this.player = Player.readFromParcel(src, world, fileversion);
|
||||
this.currentMap = world.maps.findPredefinedMap(src.readUTF());
|
||||
this.uiSelections = new InterfaceData(src, world, fileversion);
|
||||
if (uiSelections.selectedPosition != null) {
|
||||
|
||||
@@ -6,9 +6,8 @@ import java.util.Collection;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.controller.Constants;
|
||||
import com.gpl.rpg.AndorsTrail.model.CombatTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.SkillInfo.SkillLevelRequirement;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.ActorTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Player;
|
||||
|
||||
public final class SkillCollection {
|
||||
public static final int SKILL_WEAPON_CHANCE = 0;
|
||||
@@ -91,7 +90,7 @@ public final class SkillCollection {
|
||||
initializeSkill(new SkillInfo(SKILL_DODGE, SkillInfo.MAXLEVEL_NONE, SkillInfo.LEVELUP_TYPE_ALWAYS_SHOWN, null));
|
||||
initializeSkill(new SkillInfo(SKILL_BARKSKIN, MAX_LEVEL_BARKSKIN, SkillInfo.LEVELUP_TYPE_ALWAYS_SHOWN, new SkillLevelRequirement[] {
|
||||
SkillLevelRequirement.requireExperienceLevels(10, 0)
|
||||
,SkillLevelRequirement.requireCombatStats(CombatTraits.STAT_COMBAT_BLOCK_CHANCE, 15, 0)
|
||||
,SkillLevelRequirement.requireCombatStats(Player.STAT_COMBAT_BLOCK_CHANCE, 15, 0)
|
||||
}));
|
||||
initializeSkill(new SkillInfo(SKILL_MORE_CRITICALS, SkillInfo.MAXLEVEL_NONE, SkillInfo.LEVELUP_TYPE_ALWAYS_SHOWN, null));
|
||||
initializeSkill(new SkillInfo(SKILL_BETTER_CRITICALS, SkillInfo.MAXLEVEL_NONE, SkillInfo.LEVELUP_TYPE_ALWAYS_SHOWN, new SkillLevelRequirement[] {
|
||||
@@ -107,14 +106,14 @@ public final class SkillCollection {
|
||||
,SkillLevelRequirement.requireOtherSkill(SKILL_WEAPON_DMG, 1)
|
||||
}));
|
||||
initializeSkill(new SkillInfo(SKILL_EATER, SkillInfo.MAXLEVEL_NONE, SkillInfo.LEVELUP_TYPE_ALWAYS_SHOWN, new SkillLevelRequirement[] {
|
||||
SkillLevelRequirement.requireActorStats(ActorTraits.STAT_ACTOR_MAX_HP, 20, 20)
|
||||
SkillLevelRequirement.requireActorStats(Player.STAT_ACTOR_MAX_HP, 20, 20)
|
||||
}));
|
||||
initializeSkill(new SkillInfo(SKILL_FORTITUDE, SkillInfo.MAXLEVEL_NONE, SkillInfo.LEVELUP_TYPE_ALWAYS_SHOWN, new SkillLevelRequirement[] {
|
||||
SkillLevelRequirement.requireExperienceLevels(15, -10)
|
||||
}));
|
||||
initializeSkill(new SkillInfo(SKILL_EVASION, MAX_LEVEL_EVASION, SkillInfo.LEVELUP_TYPE_ALWAYS_SHOWN, null));
|
||||
initializeSkill(new SkillInfo(SKILL_REGENERATION, SkillInfo.MAXLEVEL_NONE, SkillInfo.LEVELUP_TYPE_ALWAYS_SHOWN, new SkillLevelRequirement[] {
|
||||
SkillLevelRequirement.requireActorStats(ActorTraits.STAT_ACTOR_MAX_HP, 30, 0)
|
||||
SkillLevelRequirement.requireActorStats(Player.STAT_ACTOR_MAX_HP, 30, 0)
|
||||
,SkillLevelRequirement.requireOtherSkill(SKILL_FORTITUDE, 1)
|
||||
}));
|
||||
initializeSkill(new SkillInfo(SKILL_LOWER_EXPLOSS, MAX_LEVEL_LOWER_EXPLOSS, SkillInfo.LEVELUP_TYPE_ALWAYS_SHOWN, null));
|
||||
|
||||
@@ -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.actorTraits.baseCombatTraits.getCombatStats(skillOrStatID);
|
||||
case REQUIREMENT_TYPE_ACTOR_STAT: return player.actorTraits.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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +1,77 @@
|
||||
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.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.util.Coord;
|
||||
import com.gpl.rpg.AndorsTrail.util.CoordRect;
|
||||
import com.gpl.rpg.AndorsTrail.util.Range;
|
||||
import com.gpl.rpg.AndorsTrail.util.Size;
|
||||
|
||||
public class Actor {
|
||||
public final ActorTraits actorTraits;
|
||||
public final CombatTraits combatTraits;
|
||||
public final Range ap;
|
||||
public final Range health;
|
||||
public final Coord position;
|
||||
public int iconID;
|
||||
public final Size tileSize;
|
||||
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 actorTraits, boolean isPlayer, boolean isImmuneToCriticalHits) {
|
||||
this.combatTraits = new CombatTraits(actorTraits.baseCombatTraits);
|
||||
this.actorTraits = actorTraits;
|
||||
this.ap = new Range(actorTraits.maxAP, actorTraits.maxAP);
|
||||
this.health = new Range(actorTraits.maxHP, actorTraits.maxHP);
|
||||
this.position = new Coord();
|
||||
this.rectPosition = new CoordRect(position, actorTraits.tileSize);
|
||||
public Actor(Size tileSize, boolean isPlayer, boolean isImmuneToCriticalHits) {
|
||||
this.tileSize = tileSize;
|
||||
this.rectPosition = new CoordRect(this.position, this.tileSize);
|
||||
this.isPlayer = isPlayer;
|
||||
this.isImmuneToCriticalHits = isImmuneToCriticalHits;
|
||||
}
|
||||
|
||||
public int getAttacksPerTurn() { return combatTraits.getAttacksPerTurn(actorTraits.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 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;
|
||||
@@ -63,56 +98,4 @@ public class Actor {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void resetStatsToBaseTraits() {
|
||||
combatTraits.set(actorTraits.baseCombatTraits);
|
||||
health.set(actorTraits.maxHP, health.current);
|
||||
ap.set(actorTraits.maxAP, ap.current);
|
||||
actorTraits.moveCost = actorTraits.baseMoveCost;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ====== PARCELABLE ===================================================================
|
||||
|
||||
public Actor(DataInputStream src, WorldContext world, int fileversion, boolean isPlayer, boolean isImmuneToCriticalHits, ActorTraits actorTraits) throws IOException {
|
||||
this.isPlayer = isPlayer;
|
||||
this.isImmuneToCriticalHits = isImmuneToCriticalHits;
|
||||
|
||||
CombatTraits combatTraits = null;
|
||||
boolean readCombatTraits = true;
|
||||
if (fileversion >= 25) readCombatTraits = src.readBoolean();
|
||||
if (readCombatTraits) combatTraits = new CombatTraits(src, fileversion);
|
||||
|
||||
this.actorTraits = isPlayer ? new ActorTraits(src, world, fileversion) : actorTraits;
|
||||
if (!readCombatTraits) combatTraits = new CombatTraits(this.actorTraits.baseCombatTraits);
|
||||
this.combatTraits = combatTraits;
|
||||
|
||||
this.ap = new Range(src, fileversion);
|
||||
this.health = new Range(src, fileversion);
|
||||
this.position = new Coord(src, fileversion);
|
||||
this.rectPosition = new CoordRect(position, this.actorTraits.tileSize);
|
||||
if (fileversion <= 16) return;
|
||||
final int n = src.readInt();
|
||||
for(int i = 0; i < n ; ++i) {
|
||||
conditions.add(new ActorCondition(src, world, fileversion));
|
||||
}
|
||||
}
|
||||
|
||||
public void writeToParcel(DataOutputStream dest, int flags) throws IOException {
|
||||
if (this.combatTraits.equals(actorTraits.baseCombatTraits)) {
|
||||
dest.writeBoolean(false);
|
||||
} else {
|
||||
dest.writeBoolean(true);
|
||||
combatTraits.writeToParcel(dest, flags);
|
||||
}
|
||||
if (isPlayer) actorTraits.writeToParcel(dest, flags);
|
||||
ap.writeToParcel(dest, flags);
|
||||
health.writeToParcel(dest, flags);
|
||||
position.writeToParcel(dest, flags);
|
||||
dest.writeInt(conditions.size());
|
||||
for (ActorCondition c : conditions) {
|
||||
c.writeToParcel(dest, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
package com.gpl.rpg.AndorsTrail.model.actor;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.model.CombatTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnUse;
|
||||
import com.gpl.rpg.AndorsTrail.util.Size;
|
||||
|
||||
public class ActorTraits {
|
||||
public static final int STAT_ACTOR_MAX_HP = 0;
|
||||
public static final int STAT_ACTOR_MAX_AP = 1;
|
||||
public static final int STAT_ACTOR_MOVECOST = 2;
|
||||
|
||||
public final int iconID;
|
||||
public final Size tileSize;
|
||||
|
||||
public int maxAP;
|
||||
public int maxHP;
|
||||
|
||||
public String name;
|
||||
public int moveCost;
|
||||
public final int baseMoveCost;
|
||||
|
||||
public final CombatTraits baseCombatTraits;
|
||||
public ItemTraits_OnUse[] onHitEffects;
|
||||
|
||||
public ActorTraits(
|
||||
int iconID
|
||||
, Size tileSize
|
||||
, CombatTraits baseCombatTraits
|
||||
, int standardMoveCost
|
||||
, ItemTraits_OnUse[] onHitEffects
|
||||
) {
|
||||
this.iconID = iconID;
|
||||
this.tileSize = tileSize;
|
||||
this.baseCombatTraits = baseCombatTraits;
|
||||
this.baseMoveCost = standardMoveCost;
|
||||
this.onHitEffects = onHitEffects;
|
||||
}
|
||||
public int getMovesPerTurn() {
|
||||
return (int) Math.floor(maxAP / moveCost);
|
||||
}
|
||||
|
||||
public int getActorStats(int statID) {
|
||||
switch (statID) {
|
||||
case STAT_ACTOR_MAX_HP: return maxHP;
|
||||
case STAT_ACTOR_MAX_AP: return maxAP;
|
||||
case STAT_ACTOR_MOVECOST: return moveCost;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ====== PARCELABLE ===================================================================
|
||||
|
||||
public ActorTraits(DataInputStream src, WorldContext world, int fileversion) throws IOException {
|
||||
this.iconID = src.readInt();
|
||||
this.tileSize = new Size(src, fileversion);
|
||||
this.maxAP = src.readInt();
|
||||
this.maxHP = src.readInt();
|
||||
this.name = src.readUTF();
|
||||
this.moveCost = src.readInt();
|
||||
this.baseCombatTraits = new CombatTraits(src, fileversion);
|
||||
if (fileversion <= 16) {
|
||||
this.baseMoveCost = this.moveCost;
|
||||
} else {
|
||||
this.baseMoveCost = src.readInt();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeToParcel(DataOutputStream dest, int flags) throws IOException {
|
||||
dest.writeInt(iconID);
|
||||
tileSize.writeToParcel(dest, flags);
|
||||
dest.writeInt(maxAP);
|
||||
dest.writeInt(maxHP);
|
||||
dest.writeUTF(name);
|
||||
dest.writeInt(moveCost);
|
||||
baseCombatTraits.writeToParcel(dest, flags);
|
||||
dest.writeInt(baseMoveCost);
|
||||
}
|
||||
}
|
||||
@@ -5,63 +5,89 @@ 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.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, false, monsterType.isImmuneToCriticalHits());
|
||||
this.monsterTypeID = monsterType.id;
|
||||
this.position.set(position);
|
||||
this.millisecondsPerMove = Constants.MONSTER_MOVEMENT_TURN_DURATION_MS / monsterType.getMovesPerTurn();
|
||||
this.nextPosition = new CoordRect(new Coord(), actorTraits.tileSize);
|
||||
this.phraseID = monsterType.phraseID;
|
||||
this.exp = monsterType.exp;
|
||||
this.dropList = monsterType.dropList;
|
||||
this.faction = monsterType.faction;
|
||||
this.monsterClass = monsterType.monsterClass;
|
||||
private final MonsterType monsterType;
|
||||
|
||||
public Monster(MonsterType monsterType) {
|
||||
super(monsterType.tileSize, false, monsterType.isImmuneToCriticalHits());
|
||||
this.monsterType = monsterType;
|
||||
this.iconID = monsterType.iconID;
|
||||
this.nextPosition = new CoordRect(new Coord(), monsterType.tileSize);
|
||||
resetStatsToBaseTraits();
|
||||
setMaxAP();
|
||||
setMaxHP();
|
||||
}
|
||||
|
||||
public void resetStatsToBaseTraits() {
|
||||
this.name = monsterType.name;
|
||||
this.ap.max = monsterType.maxAP;
|
||||
this.health.max = 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -74,22 +100,45 @@ public final class Monster extends Actor {
|
||||
}
|
||||
MonsterType monsterType = world.monsterTypes.getMonsterType(monsterTypeId);
|
||||
|
||||
if (fileversion < 25) return readFromParcel_pre_v0610(src, fileversion, monsterType);
|
||||
if (fileversion < 25) return LegacySavegameFormatReaderForMonster.readFromParcel_pre_v25(src, 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);
|
||||
this.monsterTypeID = monsterType.id;
|
||||
this.millisecondsPerMove = Constants.MONSTER_MOVEMENT_TURN_DURATION_MS / monsterType.getMovesPerTurn();
|
||||
this.nextPosition = new CoordRect(new Coord(), actorTraits.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();
|
||||
if (fileversion <= 20) {
|
||||
this.criticalMultiplier = src.readInt();
|
||||
} else {
|
||||
this.criticalMultiplier = src.readFloat();
|
||||
}
|
||||
this.damagePotential.set(new Range(src, fileversion));
|
||||
this.blockChance = src.readInt();
|
||||
this.damageResistance = src.readInt();
|
||||
}
|
||||
|
||||
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 (fileversion >= 31) {
|
||||
if (src.readBoolean()) {
|
||||
this.shopItems = new ItemContainer(src, world, fileversion);
|
||||
@@ -97,20 +146,36 @@ public final class Monster extends Actor {
|
||||
}
|
||||
}
|
||||
|
||||
private static Monster readFromParcel_pre_v0610(DataInputStream src, int fileversion, MonsterType monsterType) throws IOException {
|
||||
Coord position = new Coord(src, fileversion);
|
||||
Monster m = new Monster(monsterType, position);
|
||||
m.ap.current = src.readInt();
|
||||
m.health.current = src.readInt();
|
||||
if (fileversion >= 12) {
|
||||
m.forceAggressive = src.readBoolean();
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
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,11 +1,11 @@
|
||||
package com.gpl.rpg.AndorsTrail.model.actor;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.model.CombatTraits;
|
||||
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 extends ActorTraits {
|
||||
public final class MonsterType {
|
||||
public static final int MONSTERCLASS_HUMANOID = 0;
|
||||
public static final int MONSTERCLASS_INSECT = 1;
|
||||
public static final int MONSTERCLASS_DEMON = 2;
|
||||
@@ -17,6 +17,7 @@ public final class MonsterType extends ActorTraits {
|
||||
public static final int MONSTERCLASS_GHOST = 8;
|
||||
|
||||
public final String id;
|
||||
public final String name;
|
||||
public final String spawnGroup;
|
||||
public final int exp;
|
||||
public final DropList dropList;
|
||||
@@ -24,37 +25,65 @@ public final class MonsterType extends ActorTraits {
|
||||
public final boolean isUnique; // Unique monsters are not respawned.
|
||||
public final String faction;
|
||||
public final int monsterClass;
|
||||
|
||||
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,
|
||||
String name,
|
||||
String spawnGroup,
|
||||
int iconID,
|
||||
Size tileSize,
|
||||
int maxHP,
|
||||
int maxAP,
|
||||
int moveCost,
|
||||
CombatTraits baseCombatTraits,
|
||||
ItemTraits_OnUse onHitEffects,
|
||||
int exp,
|
||||
DropList dropList,
|
||||
String phraseID,
|
||||
boolean isUnique,
|
||||
String faction,
|
||||
int monsterClass) {
|
||||
super(iconID, tileSize, baseCombatTraits, moveCost, onHitEffects == null ? null : new ItemTraits_OnUse[] { onHitEffects });
|
||||
int monsterClass,
|
||||
Size tileSize,
|
||||
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;
|
||||
this.exp = exp;
|
||||
this.name = name;
|
||||
this.maxHP = maxHP;
|
||||
this.maxAP = maxAP;
|
||||
this.moveCost = moveCost;
|
||||
this.dropList = dropList;
|
||||
this.phraseID = phraseID;
|
||||
this.faction = faction;
|
||||
this.isUnique = isUnique;
|
||||
this.monsterClass = monsterClass;
|
||||
this.tileSize = tileSize;
|
||||
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() {
|
||||
@@ -63,4 +92,15 @@ public final class MonsterType extends ActorTraits {
|
||||
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 != null) return true;
|
||||
if (blockChance != 0) return true;
|
||||
if (damageResistance != 0) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,38 +14,90 @@ 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.controller.ItemController;
|
||||
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.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.util.Coord;
|
||||
import com.gpl.rpg.AndorsTrail.util.Range;
|
||||
import com.gpl.rpg.AndorsTrail.util.Size;
|
||||
|
||||
public final class Player extends Actor {
|
||||
public static final int DEFAULT_PLAYER_MOVECOST = 6;
|
||||
public static final int STAT_ACTOR_MAX_HP = 0;
|
||||
public static final int STAT_ACTOR_MAX_AP = 1;
|
||||
public static final int STAT_ACTOR_MOVECOST = 2;
|
||||
public static final int STAT_COMBAT_ATTACK_COST = 0;
|
||||
public static final int STAT_COMBAT_ATTACK_CHANCE = 1;
|
||||
public static final int STAT_COMBAT_CRITICAL_SKILL = 2;
|
||||
public static final int STAT_COMBAT_CRITICAL_MULTIPLIER = 3;
|
||||
public static final int STAT_COMBAT_DAMAGE_POTENTIAL_MIN = 4;
|
||||
public static final int STAT_COMBAT_DAMAGE_POTENTIAL_MAX = 5;
|
||||
public static final int STAT_COMBAT_BLOCK_CHANCE = 6;
|
||||
public static final int STAT_COMBAT_DAMAGE_RESISTANCE = 7;
|
||||
|
||||
public static final int DEFAULT_PLAYER_ATTACKCOST = 4;
|
||||
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>();
|
||||
|
||||
// Unequipped stats
|
||||
public class PlayerBaseTraits {
|
||||
public int iconID;
|
||||
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.iconID = this.baseTraits.iconID;
|
||||
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, new Size(1, 1), new CombatTraits(), DEFAULT_PLAYER_MOVECOST, null), true, false);
|
||||
super(
|
||||
new Size(1, 1)
|
||||
, true // isPlayer
|
||||
, false // isImmuneToCriticalHits
|
||||
);
|
||||
this.lastPosition = new Coord();
|
||||
this.nextPosition = new Coord();
|
||||
this.levelExperience = new Range();
|
||||
@@ -53,45 +105,44 @@ public final class Player extends Actor {
|
||||
}
|
||||
|
||||
public void initializeNewPlayer(ItemTypeCollection types, DropListCollection dropLists, String name) {
|
||||
CombatTraits combat = new CombatTraits();
|
||||
combat.attackCost = DEFAULT_PLAYER_ATTACKCOST;
|
||||
combat.attackChance = 60;
|
||||
combat.criticalSkill = 0;
|
||||
combat.criticalMultiplier = 1;
|
||||
combat.damagePotential.set(1, 1);
|
||||
combat.blockChance = 0;
|
||||
combat.damageResistance = 0;
|
||||
|
||||
actorTraits.baseCombatTraits.set(combat);
|
||||
|
||||
actorTraits.maxAP = 10;
|
||||
actorTraits.maxHP = 25;
|
||||
|
||||
actorTraits.name = name;
|
||||
actorTraits.moveCost = DEFAULT_PLAYER_MOVECOST;
|
||||
useItemCost = 5;
|
||||
reequipCost = 5;
|
||||
|
||||
level = 1;
|
||||
totalExperience = 1;
|
||||
availableSkillIncreases = 0;
|
||||
skillLevels.clear();
|
||||
alignments.clear();
|
||||
recalculateLevelExperience();
|
||||
baseTraits.iconID = TileManager.CHAR_HERO;
|
||||
baseTraits.maxAP = 10;
|
||||
baseTraits.maxHP = 25;
|
||||
baseTraits.moveCost = 6;
|
||||
baseTraits.attackCost = DEFAULT_PLAYER_ATTACKCOST;
|
||||
baseTraits.attackChance = 60;
|
||||
baseTraits.criticalSkill = 0;
|
||||
baseTraits.criticalMultiplier = 1;
|
||||
baseTraits.damagePotential.set(1, 1);
|
||||
baseTraits.blockChance = 0;
|
||||
baseTraits.damageResistance = 0;
|
||||
baseTraits.useItemCost = 5;
|
||||
baseTraits.reequipCost = 5;
|
||||
this.name = name;
|
||||
this.level = 1;
|
||||
this.totalExperience = 1;
|
||||
this.inventory.clear();
|
||||
this.questProgress.clear();
|
||||
this.skillLevels.clear();
|
||||
this.availableSkillIncreases = 0;
|
||||
this.alignments.clear();
|
||||
this.ap.set(baseTraits.maxAP, baseTraits.maxAP);
|
||||
this.health.set(baseTraits.maxHP, baseTraits.maxHP);
|
||||
this.conditions.clear();
|
||||
|
||||
Loot startItems = new Loot();
|
||||
dropLists.getDropList(DropListCollection.DROPLIST_STARTITEMS).createRandomLoot(startItems, this);
|
||||
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);
|
||||
ActorStatsController.recalculatePlayerStats(this);
|
||||
}
|
||||
|
||||
public boolean hasExactQuestProgress(QuestProgress progress) { return hasExactQuestProgress(progress.questID, progress.progress); }
|
||||
@@ -144,7 +195,7 @@ public final class Player extends Actor {
|
||||
}
|
||||
public void addSkillLevel(int skillID) {
|
||||
skillLevels.put(skillID, skillLevels.get(skillID) + 1);
|
||||
ActorStatsController.recalculatePlayerCombatTraits(this);
|
||||
ActorStatsController.recalculatePlayerStats(this);
|
||||
}
|
||||
public boolean nextLevelAddsNewSkillpoint() {
|
||||
return thisLevelAddsNewSkillpoint(level + 1);
|
||||
@@ -152,11 +203,6 @@ public final class Player extends Actor {
|
||||
public static boolean thisLevelAddsNewSkillpoint(int level) {
|
||||
return ((level - Constants.FIRST_SKILL_POINT_IS_GIVEN_AT_LEVEL) % Constants.NEW_SKILL_POINT_EVERY_N_LEVELS == 0);
|
||||
}
|
||||
public static int getExpectedNumberOfSkillpointsForLevel(int level) {
|
||||
level -= Constants.FIRST_SKILL_POINT_IS_GIVEN_AT_LEVEL;
|
||||
if (level < 0) return 0;
|
||||
return 1 + (int) FloatMath.floor((float) level / Constants.NEW_SKILL_POINT_EVERY_N_LEVELS);
|
||||
}
|
||||
public boolean hasAvailableSkillpoints() {
|
||||
return availableSkillIncreases > 0;
|
||||
}
|
||||
@@ -171,68 +217,108 @@ 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 Player.STAT_ACTOR_MAX_HP: return baseTraits.maxHP;
|
||||
case Player.STAT_ACTOR_MAX_AP: return baseTraits.maxAP;
|
||||
case Player.STAT_ACTOR_MOVECOST: return baseTraits.moveCost;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getCombatStats(int statID) {
|
||||
switch (statID) {
|
||||
case Player.STAT_COMBAT_ATTACK_COST: return baseTraits.attackCost;
|
||||
case Player.STAT_COMBAT_ATTACK_CHANCE: return baseTraits.attackChance;
|
||||
case Player.STAT_COMBAT_CRITICAL_SKILL: return baseTraits.criticalSkill;
|
||||
case Player.STAT_COMBAT_CRITICAL_MULTIPLIER: return (int) FloatMath.floor(baseTraits.criticalMultiplier);
|
||||
case Player.STAT_COMBAT_DAMAGE_POTENTIAL_MIN: return baseTraits.damagePotential.current;
|
||||
case Player.STAT_COMBAT_DAMAGE_POTENTIAL_MAX: return baseTraits.damagePotential.max;
|
||||
case Player.STAT_COMBAT_BLOCK_CHANCE: return baseTraits.blockChance;
|
||||
case Player.STAT_COMBAT_DAMAGE_RESISTANCE: return baseTraits.damageResistance;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ====== PARCELABLE ===================================================================
|
||||
|
||||
public static Player readFromParcel(DataInputStream src, WorldContext world, int fileversion) throws IOException {
|
||||
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, null);
|
||||
this.lastPosition = new Coord(src, fileversion);
|
||||
this.nextPosition = new Coord(src, fileversion);
|
||||
this.level = src.readInt();
|
||||
this.totalExperience = src.readInt();
|
||||
this.levelExperience = new Range();
|
||||
this.recalculateLevelExperience();
|
||||
this.inventory = new Inventory(src, world, fileversion);
|
||||
this();
|
||||
|
||||
if (fileversion <= 13) {
|
||||
final int size1 = src.readInt();
|
||||
for(int i = 0; i < size1; ++i) {
|
||||
String keyName = src.readUTF();
|
||||
if ("mikhail_visited".equals(keyName)) addQuestProgress(new QuestProgress("andor", 1));
|
||||
else if ("qmikhail_bread_complete".equals(keyName)) addQuestProgress(new QuestProgress("mikhail_bread", 100));
|
||||
else if ("qmikhail_bread".equals(keyName)) addQuestProgress(new QuestProgress("mikhail_bread", 10));
|
||||
else if ("qmikhail_rats_complete".equals(keyName)) addQuestProgress(new QuestProgress("mikhail_rats", 100));
|
||||
else if ("qmikhail_rats".equals(keyName)) addQuestProgress(new QuestProgress("mikhail_rats", 10));
|
||||
else if ("oromir".equals(keyName)) addQuestProgress(new QuestProgress("leta", 20));
|
||||
else if ("qleta_complete".equals(keyName)) addQuestProgress(new QuestProgress("leta", 100));
|
||||
else if ("qodair".equals(keyName)) addQuestProgress(new QuestProgress("odair", 10));
|
||||
else if ("qodair_complete".equals(keyName)) addQuestProgress(new QuestProgress("odair", 100));
|
||||
else if ("qleonid_bonemeal".equals(keyName)) {
|
||||
addQuestProgress(new QuestProgress("bonemeal", 10));
|
||||
addQuestProgress(new QuestProgress("bonemeal", 20));
|
||||
}
|
||||
else if ("qtharal_complete".equals(keyName)) addQuestProgress(new QuestProgress("bonemeal", 30));
|
||||
else if ("qthoronir_complete".equals(keyName)) addQuestProgress(new QuestProgress("bonemeal", 100));
|
||||
else if ("qleonid_andor".equals(keyName)) addQuestProgress(new QuestProgress("andor", 10));
|
||||
else if ("qgruil_andor".equals(keyName)) addQuestProgress(new QuestProgress("andor", 20));
|
||||
else if ("qgruil_andor_complete".equals(keyName)) addQuestProgress(new QuestProgress("andor", 30));
|
||||
else if ("qleonid_crossglen".equals(keyName)) addQuestProgress(new QuestProgress("crossglen", 1));
|
||||
else if ("qjan".equals(keyName)) addQuestProgress(new QuestProgress("jan", 10));
|
||||
else if ("qjan_complete".equals(keyName)) addQuestProgress(new QuestProgress("jan", 100));
|
||||
else if ("qbucus_thieves".equals(keyName)) addQuestProgress(new QuestProgress("andor", 40));
|
||||
else if ("qfallhaven_derelict".equals(keyName)) addQuestProgress(new QuestProgress("andor", 50));
|
||||
else if ("qfallhaven_drunk".equals(keyName)) addQuestProgress(new QuestProgress("fallhavendrunk", 10));
|
||||
else if ("qfallhaven_drunk_complete".equals(keyName)) addQuestProgress(new QuestProgress("fallhavendrunk", 100));
|
||||
else if ("qnocmar_unnmir".equals(keyName)) addQuestProgress(new QuestProgress("nocmar", 10));
|
||||
else if ("qnocmar".equals(keyName)) addQuestProgress(new QuestProgress("nocmar", 20));
|
||||
else if ("qnocmar_complete".equals(keyName)) addQuestProgress(new QuestProgress("nocmar", 200));
|
||||
else if ("qfallhaven_tavern_room2".equals(keyName)) addQuestProgress(new QuestProgress("fallhaventavern", 10));
|
||||
else if ("qarcir".equals(keyName)) addQuestProgress(new QuestProgress("arcir", 10));
|
||||
else if ("qfallhaven_oldman".equals(keyName)) addQuestProgress(new QuestProgress("calomyran", 10));
|
||||
else if ("qcalomyran_tornpage".equals(keyName)) addQuestProgress(new QuestProgress("calomyran", 20));
|
||||
else if ("qfallhaven_oldman_complete".equals(keyName)) addQuestProgress(new QuestProgress("calomyran", 100));
|
||||
else if ("qbucus".equals(keyName)) addQuestProgress(new QuestProgress("bucus", 10));
|
||||
else if ("qthoronir_catacombs".equals(keyName)) addQuestProgress(new QuestProgress("bucus", 20));
|
||||
else if ("qathamyr_complete".equals(keyName)) addQuestProgress(new QuestProgress("bucus", 40));
|
||||
else if ("qfallhaven_church".equals(keyName)) addQuestProgress(new QuestProgress("bucus", 50));
|
||||
else if ("qbucus_complete".equals(keyName)) addQuestProgress(new QuestProgress("bucus", 100));
|
||||
if (fileversion <= 33) LegacySavegameFormatReaderForPlayer.readCombatTraitsPreV034(src, fileversion);
|
||||
|
||||
this.baseTraits.iconID = src.readInt();
|
||||
if (fileversion <= 33) /*this.tileSize = */new Size(src, fileversion);
|
||||
this.baseTraits.maxAP = src.readInt();
|
||||
this.baseTraits.maxHP = src.readInt();
|
||||
this.name = src.readUTF();
|
||||
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 numConditions = src.readInt();
|
||||
for(int i = 0; i < numConditions; ++i) {
|
||||
this.conditions.add(new ActorCondition(src, world, fileversion));
|
||||
}
|
||||
}
|
||||
this.useItemCost = src.readInt();
|
||||
this.reequipCost = src.readInt();
|
||||
final int size2 = src.readInt();
|
||||
for(int i = 0; i < size2; ++i) {
|
||||
|
||||
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.baseTraits.useItemCost = src.readInt();
|
||||
this.baseTraits.reequipCost = src.readInt();
|
||||
final int numSkills = src.readInt();
|
||||
for(int i = 0; i < numSkills; ++i) {
|
||||
if (fileversion <= 21) {
|
||||
this.skillLevels.put(i, src.readInt());
|
||||
} else {
|
||||
@@ -242,69 +328,64 @@ public final class Player extends Actor {
|
||||
}
|
||||
this.spawnMap = src.readUTF();
|
||||
this.spawnPlace = src.readUTF();
|
||||
|
||||
if (fileversion <= 12) {
|
||||
useItemCost = 5;
|
||||
health.max += 5;
|
||||
health.current += 5;
|
||||
actorTraits.maxHP += 5;
|
||||
}
|
||||
|
||||
if (fileversion <= 13) return;
|
||||
|
||||
final int numquests = src.readInt();
|
||||
for(int i = 0; i < numquests; ++i) {
|
||||
final String questID = src.readUTF();
|
||||
questProgress.put(questID, new HashSet<Integer>());
|
||||
final int numprogress = src.readInt();
|
||||
for(int j = 0; j < numprogress; ++j) {
|
||||
int progress = src.readInt();
|
||||
questProgress.get(questID).add(progress);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fileversion <= 21) {
|
||||
int assignedSkillpoints = 0;
|
||||
for (int i = 0; i < skillLevels.size(); ++i) assignedSkillpoints += skillLevels.valueAt(i);
|
||||
this.availableSkillIncreases = getExpectedNumberOfSkillpointsForLevel(this.level) - assignedSkillpoints;
|
||||
} else {
|
||||
this.availableSkillIncreases = 0;
|
||||
if (fileversion > 21) {
|
||||
this.availableSkillIncreases = src.readInt();
|
||||
}
|
||||
|
||||
if (fileversion <= 21) {
|
||||
if (hasExactQuestProgress("prim_hunt", 240)) addQuestProgress(new QuestProgress("bwm_agent", 250));
|
||||
if (hasExactQuestProgress("bwm_agent", 240)) addQuestProgress(new QuestProgress("prim_hunt", 250));
|
||||
}
|
||||
|
||||
if (fileversion >= 26) {
|
||||
final int size3 = src.readInt();
|
||||
for(int i = 0; i < size3; ++i) {
|
||||
final int numAlignments = src.readInt();
|
||||
for(int i = 0; i < numAlignments; ++i) {
|
||||
final String faction = src.readUTF();
|
||||
final int alignment = src.readInt();
|
||||
alignments.put(faction, alignment);
|
||||
this.alignments.put(faction, alignment);
|
||||
}
|
||||
}
|
||||
|
||||
if (fileversion <= 27) {
|
||||
ItemController.correctActorConditionsFromItemsPre0611b1(this, "bless", world, "elytharan_redeemer");
|
||||
ItemController.correctActorConditionsFromItemsPre0611b1(this, "blackwater_misery", world, "bwm_dagger");
|
||||
ItemController.correctActorConditionsFromItemsPre0611b1(this, "regen", world, "ring_shadow0");
|
||||
}
|
||||
|
||||
if (fileversion <= 30) {
|
||||
this.actorTraits.baseCombatTraits.attackCost = DEFAULT_PLAYER_ATTACKCOST;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void writeToParcel(DataOutputStream dest, int flags) throws IOException {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeInt(baseTraits.iconID);
|
||||
dest.writeInt(baseTraits.maxAP);
|
||||
dest.writeInt(baseTraits.maxHP);
|
||||
dest.writeUTF(name);
|
||||
dest.writeInt(moveCost); // TODO: Should we really write this?
|
||||
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);
|
||||
dest.writeInt(totalExperience);
|
||||
inventory.writeToParcel(dest, flags);
|
||||
dest.writeInt(useItemCost);
|
||||
dest.writeInt(reequipCost);
|
||||
dest.writeInt(baseTraits.useItemCost);
|
||||
dest.writeInt(baseTraits.reequipCost);
|
||||
dest.writeInt(skillLevels.size());
|
||||
for (int i = 0; i < skillLevels.size(); ++i) {
|
||||
dest.writeInt(skillLevels.keyAt(i));
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.savegames.LegacySavegameFormatReaderForItemContainer;
|
||||
|
||||
public final class Inventory extends ItemContainer {
|
||||
|
||||
@@ -26,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);
|
||||
@@ -55,26 +63,32 @@ 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) this.gold += ItemContainer.SavegameUpdate.refundUpgradedItems(this);
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (fileversion < 19) return;
|
||||
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;
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,7 @@ import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.util.L;
|
||||
|
||||
public class ItemContainer {
|
||||
public final ArrayList<ItemEntry> items = new ArrayList<ItemEntry>();
|
||||
@@ -120,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);
|
||||
@@ -133,28 +136,4 @@ public class ItemContainer {
|
||||
e.writeToParcel(dest, flags);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SavegameUpdate {
|
||||
public static int refundUpgradedItems(ItemContainer container) {
|
||||
int removedCost = 0;
|
||||
for (ItemEntry e : container.items) {
|
||||
if (e.quantity >= 2 && isRefundableItem(e.itemType)) {
|
||||
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) {
|
||||
L.log("INFO: Refunding " + (e.quantity-1) + " items of type \"" + e.itemType.id + "\" for a total of " + ((e.quantity-1) * e.itemType.fixedBaseMarketCost) + "gc.");
|
||||
}
|
||||
removedCost += (e.quantity-1) * e.itemType.fixedBaseMarketCost;
|
||||
e.quantity = 1;
|
||||
}
|
||||
}
|
||||
return removedCost;
|
||||
}
|
||||
|
||||
private static boolean isRefundableItem(ItemType itemType) {
|
||||
if (itemType.hasManualPrice) return false;
|
||||
if (itemType.isQuestItem()) return false;
|
||||
if (itemType.displayType == ItemType.DISPLAYTYPE_EXTRAORDINARY) return false;
|
||||
if (itemType.displayType == ItemType.DISPLAYTYPE_LEGENDARY) return false;
|
||||
return itemType.baseMarketCost > itemType.fixedBaseMarketCost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,20 @@ package com.gpl.rpg.AndorsTrail.model.item;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionEffect;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.traits.StatsModifierTraits;
|
||||
import com.gpl.rpg.AndorsTrail.util.ConstRange;
|
||||
|
||||
public final class ItemTraits_OnUse extends StatsModifierTraits {
|
||||
public final class ItemTraits_OnUse {
|
||||
public final StatsModifierTraits changedStats;
|
||||
public final ActorConditionEffect[] addedConditions_source;
|
||||
public final ActorConditionEffect[] addedConditions_target;
|
||||
|
||||
public ItemTraits_OnUse(int visualEffectID, ConstRange currentHPBoost, ConstRange currentAPBoost, ActorConditionEffect[] addedConditions_source, ActorConditionEffect[] addedConditions_target) {
|
||||
super(visualEffectID, currentHPBoost, currentAPBoost);
|
||||
public ItemTraits_OnUse(StatsModifierTraits changedStats, ActorConditionEffect[] addedConditions_source, ActorConditionEffect[] addedConditions_target) {
|
||||
this.changedStats = changedStats;
|
||||
this.addedConditions_source = addedConditions_source;
|
||||
this.addedConditions_target = addedConditions_target;
|
||||
}
|
||||
|
||||
public int calculateCost() {
|
||||
final int costStats = changedStats == null ? 0 : changedStats.calculateCost();
|
||||
return costStats;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public final class ItemType {
|
||||
|
||||
public String getName(Player p) {
|
||||
if (!hasPersonalizedName) return name;
|
||||
else return name.replace(Constants.PLACEHOLDER_PLAYERNAME, p.actorTraits.name);
|
||||
else return name.replace(Constants.PLACEHOLDER_PLAYERNAME, p.getName());
|
||||
}
|
||||
|
||||
public int getOverlayTileID() {
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.savegames.LegacySavegameFormatReaderForItemContainer;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
|
||||
public final class Loot {
|
||||
@@ -51,7 +52,7 @@ public final class Loot {
|
||||
this.exp = src.readInt();
|
||||
this.gold = src.readInt();
|
||||
this.items = new ItemContainer(src, world, fileversion);
|
||||
if (fileversion < 23) this.gold += ItemContainer.SavegameUpdate.refundUpgradedItems(this.items);
|
||||
if (fileversion < 23) LegacySavegameFormatReaderForItemContainer.refundUpgradedItems(this);
|
||||
|
||||
this.position = new Coord(src, fileversion);
|
||||
if (fileversion <= 15) {
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionEffect;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionTypeCollection;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.traits.AbilityModifierTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.traits.StatsModifierTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnEquip;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnUse;
|
||||
import com.gpl.rpg.AndorsTrail.resource.ResourceFileTokenizer;
|
||||
@@ -49,8 +50,8 @@ public final class ItemTraitsParser {
|
||||
boolean hasEffect = ResourceParserUtils.parseBoolean(parts[startIndex], false);
|
||||
if (!hasEffect) return null;
|
||||
|
||||
ConstRange boostCurrentHP = ResourceParserUtils.parseRange(parts[startIndex + 1], parts[startIndex + 2]);
|
||||
ConstRange boostCurrentAP = ResourceParserUtils.parseRange(parts[startIndex + 3], parts[startIndex + 4]);
|
||||
ConstRange boostCurrentHP = ResourceParserUtils.parseConstRange(parts[startIndex + 1], parts[startIndex + 2]);
|
||||
ConstRange boostCurrentAP = ResourceParserUtils.parseConstRange(parts[startIndex + 3], parts[startIndex + 4]);
|
||||
final ArrayList<ActorConditionEffect> addedConditions_source = new ArrayList<ActorConditionEffect>();
|
||||
final ArrayList<ActorConditionEffect> addedConditions_target = new ArrayList<ActorConditionEffect>();
|
||||
tokenize4Fields.tokenizeArray(parts[startIndex + 5], addedConditions_source, actorConditionEffectParser_withDuration);
|
||||
@@ -68,9 +69,11 @@ public final class ItemTraitsParser {
|
||||
return null;
|
||||
} else {
|
||||
return new ItemTraits_OnUse(
|
||||
ItemTraits_OnUse.VISUAL_EFFECT_NONE
|
||||
,boostCurrentHP
|
||||
,boostCurrentAP
|
||||
new StatsModifierTraits(
|
||||
StatsModifierTraits.VISUAL_EFFECT_NONE
|
||||
,boostCurrentHP
|
||||
,boostCurrentAP
|
||||
)
|
||||
,listToArray(addedConditions_source)
|
||||
,listToArray(addedConditions_target)
|
||||
);
|
||||
|
||||
@@ -3,13 +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.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;
|
||||
|
||||
@@ -29,43 +29,70 @@ public final class MonsterTypeParser extends ResourceParserFor<MonsterType> {
|
||||
|
||||
@Override
|
||||
public Pair<String, MonsterType> parseRow(String[] parts) {
|
||||
final String monsterTypeId = parts[0];
|
||||
final int maxHP = ResourceParserUtils.parseInt(parts[8], 1);
|
||||
final int maxAP = ResourceParserUtils.parseInt(parts[9], 10);
|
||||
final CombatTraits combatTraits = ResourceParserUtils.parseCombatTraits(parts, 11);
|
||||
final ItemTraits_OnUse hitEffect = itemTraitsParser.parseItemTraits_OnUse(parts, 21, true);
|
||||
final int exp = getExpectedMonsterExperience(combatTraits, hitEffect, maxHP, maxAP);
|
||||
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(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
|
||||
, ResourceParserUtils.parseImageID(tileLoader, parts[1])
|
||||
, ResourceParserUtils.parseSize(parts[4], size1x1) //TODO: This could be loaded from the tileset size instead.
|
||||
, maxHP // HP
|
||||
, maxAP // AP
|
||||
, ResourceParserUtils.parseInt(parts[10], 10) // MoveCost
|
||||
, combatTraits
|
||||
, hitEffect
|
||||
, parts[3] // SpawnGroup
|
||||
, exp // Exp
|
||||
, droplists.getDropList(parts[19]) // Droplist
|
||||
, ResourceParserUtils.parseNullableString(parts[20]) // PhraseID
|
||||
, ResourceParserUtils.parseBoolean(parts[6], false) // isUnique
|
||||
, 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.
|
||||
, 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.gpl.rpg.AndorsTrail.resource.parsers;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
import com.gpl.rpg.AndorsTrail.model.CombatTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.traits.AbilityModifierTraits;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.traits.StatsModifierTraits;
|
||||
import com.gpl.rpg.AndorsTrail.resource.DynamicTileLoader;
|
||||
import com.gpl.rpg.AndorsTrail.util.ConstRange;
|
||||
import com.gpl.rpg.AndorsTrail.util.L;
|
||||
import com.gpl.rpg.AndorsTrail.util.Range;
|
||||
import com.gpl.rpg.AndorsTrail.util.Size;
|
||||
|
||||
public final class ResourceParserUtils {
|
||||
@@ -15,7 +15,27 @@ public final class ResourceParserUtils {
|
||||
String[] parts = s.split(":");
|
||||
return tileLoader.prepareTileID(parts[0], Integer.parseInt(parts[1]));
|
||||
}
|
||||
public static ConstRange parseRange(String min, String max) {
|
||||
public static Range parseRange(String min, String max) {
|
||||
if ( (max == null || max.length() <= 0)
|
||||
&& (min == null || min.length() <= 0) ) {
|
||||
return null;
|
||||
}
|
||||
if (max == null || max.length() <= 0) {
|
||||
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
|
||||
L.log("OPTIMIZE: Unable to parse range with min=" + min + " because max was empty.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (min == null || min.length() <= 0) {
|
||||
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
|
||||
L.log("OPTIMIZE: Unable to parse range with max=" + max + " because min was empty.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Range(Integer.parseInt(max), Integer.parseInt(min));
|
||||
}
|
||||
public static ConstRange parseConstRange(String min, String max) {
|
||||
if ( (max == null || max.length() <= 0)
|
||||
&& (min == null || min.length() <= 0) ) {
|
||||
return null;
|
||||
@@ -45,35 +65,6 @@ public final class ResourceParserUtils {
|
||||
return new Size(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]));
|
||||
}
|
||||
|
||||
public static CombatTraits parseCombatTraits(String[] parts, int startIndex) {
|
||||
String attackCost = parts[startIndex];
|
||||
String attackChance = parts[startIndex + 1];
|
||||
String criticalSkill = parts[startIndex + 2];
|
||||
String criticalMultiplier = parts[startIndex + 3];
|
||||
ConstRange attackDamage = parseRange(parts[startIndex + 4], parts[startIndex + 5]);
|
||||
String blockChance = parts[startIndex + 6];
|
||||
String damageResistance = parts[startIndex + 7];
|
||||
if ( attackCost.length() <= 0
|
||||
&& attackChance.length() <= 0
|
||||
&& criticalSkill.length() <= 0
|
||||
&& criticalMultiplier.length() <= 0
|
||||
&& attackDamage == null
|
||||
&& blockChance.length() <= 0
|
||||
&& damageResistance.length() <= 0
|
||||
) {
|
||||
return null;
|
||||
} else {
|
||||
CombatTraits result = new CombatTraits();
|
||||
result.attackCost = parseInt(attackCost, 0);
|
||||
result.attackChance = parseInt(attackChance, 0);
|
||||
result.criticalSkill = parseInt(criticalSkill, 0);
|
||||
result.criticalMultiplier = parseFloat(criticalMultiplier, 0);
|
||||
if (attackDamage != null) result.damagePotential.set(attackDamage);
|
||||
result.blockChance = parseInt(blockChance, 0);
|
||||
result.damageResistance = parseInt(damageResistance, 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
public static String parseNullableString(String s) {
|
||||
if (s == null || s.length() <= 0) return null;
|
||||
return s;
|
||||
@@ -102,8 +93,8 @@ public final class ResourceParserUtils {
|
||||
if (!hasEffect) return null;
|
||||
|
||||
String visualEffectID = parts[startIndex + 1];
|
||||
ConstRange boostCurrentHP = parseRange(parts[startIndex + 2], parts[startIndex + 3]);
|
||||
ConstRange boostCurrentAP = parseRange(parts[startIndex + 4], parts[startIndex + 5]);
|
||||
ConstRange boostCurrentHP = parseConstRange(parts[startIndex + 2], parts[startIndex + 3]);
|
||||
ConstRange boostCurrentAP = parseConstRange(parts[startIndex + 4], parts[startIndex + 5]);
|
||||
if ( boostCurrentHP == null
|
||||
&& boostCurrentAP == null
|
||||
) {
|
||||
@@ -174,7 +165,7 @@ public final class ResourceParserUtils {
|
||||
else if (min.equals("1") && max.equals("1")) return one;
|
||||
else if (min.equals("5") && max.equals("5")) return five;
|
||||
else if (min.equals("10") && max.equals("10")) return ten;
|
||||
return parseRange(min, max);
|
||||
return parseConstRange(min, max);
|
||||
}
|
||||
|
||||
public static final ConstRange always = one;
|
||||
|
||||
@@ -125,8 +125,8 @@ public final class TileManager {
|
||||
|
||||
|
||||
|
||||
public void setImageViewTile(TextView textView, Monster monster) { setImageViewTileForMonster(textView, monster.actorTraits.iconID); }
|
||||
public void setImageViewTile(TextView textView, Player player) { setImageViewTileForPlayer(textView, player.actorTraits.iconID); }
|
||||
public void setImageViewTile(TextView textView, Monster monster) { setImageViewTileForMonster(textView, monster.iconID); }
|
||||
public void setImageViewTile(TextView textView, Player player) { setImageViewTileForPlayer(textView, player.iconID); }
|
||||
public void setImageViewTileForMonster(TextView textView, int iconID) { setImageViewTile(textView, currentMapTiles.getBitmap(iconID)); }
|
||||
public void setImageViewTileForPlayer(TextView textView, int iconID) { setImageViewTile(textView, preloadedTiles.getBitmap(iconID)); }
|
||||
public void setImageViewTile(TextView textView, ActorConditionType conditionType) { setImageViewTile(textView, preloadedTiles.getBitmap(conditionType.iconID)); }
|
||||
@@ -155,8 +155,8 @@ public final class TileManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void setImageViewTile(ImageView imageView, Monster monster) { setImageViewTileForMonster(imageView, monster.actorTraits.iconID); }
|
||||
public void setImageViewTile(ImageView imageView, Player player) { setImageViewTileForPlayer(imageView, player.actorTraits.iconID); }
|
||||
public void setImageViewTile(ImageView imageView, Monster monster) { setImageViewTileForMonster(imageView, monster.iconID); }
|
||||
public void setImageViewTile(ImageView imageView, Player player) { setImageViewTileForPlayer(imageView, player.iconID); }
|
||||
public void setImageViewTileForMonster(ImageView imageView, int iconID) { imageView.setImageBitmap(currentMapTiles.getBitmap(iconID)); }
|
||||
public void setImageViewTileForPlayer(ImageView imageView, int iconID) { imageView.setImageBitmap(preloadedTiles.getBitmap(iconID)); }
|
||||
public void setImageViewTile(ImageView imageView, ActorConditionType conditionType) { imageView.setImageBitmap(preloadedTiles.getBitmap(conditionType.iconID)); }
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.gpl.rpg.AndorsTrail.savegames;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.Inventory;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemContainer;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemContainer.ItemEntry;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.Loot;
|
||||
import com.gpl.rpg.AndorsTrail.util.L;
|
||||
|
||||
public final class LegacySavegameFormatReaderForItemContainer {
|
||||
public static void refundUpgradedItems(Inventory inventory) {
|
||||
inventory.gold += getRefundForUpgradedItems(inventory);
|
||||
}
|
||||
public static void refundUpgradedItems(Loot loot) {
|
||||
loot.gold += getRefundForUpgradedItems(loot.items);
|
||||
}
|
||||
|
||||
private static int getRefundForUpgradedItems(ItemContainer container) {
|
||||
int removedCost = 0;
|
||||
for (ItemEntry e : container.items) {
|
||||
if (e.quantity >= 2 && isRefundableItem(e.itemType)) {
|
||||
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) {
|
||||
L.log("INFO: Refunding " + (e.quantity-1) + " items of type \"" + e.itemType.id + "\" for a total of " + ((e.quantity-1) * e.itemType.fixedBaseMarketCost) + "gc.");
|
||||
}
|
||||
removedCost += (e.quantity-1) * e.itemType.fixedBaseMarketCost;
|
||||
e.quantity = 1;
|
||||
}
|
||||
}
|
||||
return removedCost;
|
||||
}
|
||||
|
||||
private static boolean isRefundableItem(ItemType itemType) {
|
||||
if (itemType.hasManualPrice) return false;
|
||||
if (itemType.isQuestItem()) return false;
|
||||
if (itemType.displayType == ItemType.DISPLAYTYPE_EXTRAORDINARY) return false;
|
||||
if (itemType.displayType == ItemType.DISPLAYTYPE_LEGENDARY) return false;
|
||||
return itemType.baseMarketCost > itemType.fixedBaseMarketCost;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.gpl.rpg.AndorsTrail.savegames;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Monster;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.MonsterType;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
|
||||
public class LegacySavegameFormatReaderForMonster {
|
||||
public static Monster readFromParcel_pre_v25(DataInputStream src, int fileversion, MonsterType monsterType) throws IOException {
|
||||
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) {
|
||||
if (src.readBoolean()) m.forceAggressive();
|
||||
}
|
||||
return m;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.gpl.rpg.AndorsTrail.savegames;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import android.util.FloatMath;
|
||||
|
||||
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.ability.ActorConditionEffect;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.SkillInfo;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Player;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemType;
|
||||
import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress;
|
||||
import com.gpl.rpg.AndorsTrail.util.Range;
|
||||
|
||||
public final class LegacySavegameFormatReaderForPlayer {
|
||||
|
||||
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();
|
||||
if ("mikhail_visited".equals(keyName)) addQuestProgress(player, "andor", 1);
|
||||
else if ("qmikhail_bread_complete".equals(keyName)) addQuestProgress(player, "mikhail_bread", 100);
|
||||
else if ("qmikhail_bread".equals(keyName)) addQuestProgress(player, "mikhail_bread", 10);
|
||||
else if ("qmikhail_rats_complete".equals(keyName)) addQuestProgress(player, "mikhail_rats", 100);
|
||||
else if ("qmikhail_rats".equals(keyName)) addQuestProgress(player, "mikhail_rats", 10);
|
||||
else if ("oromir".equals(keyName)) addQuestProgress(player, "leta", 20);
|
||||
else if ("qleta_complete".equals(keyName)) addQuestProgress(player, "leta", 100);
|
||||
else if ("qodair".equals(keyName)) addQuestProgress(player, "odair", 10);
|
||||
else if ("qodair_complete".equals(keyName)) addQuestProgress(player, "odair", 100);
|
||||
else if ("qleonid_bonemeal".equals(keyName)) {
|
||||
addQuestProgress(player, "bonemeal", 10);
|
||||
addQuestProgress(player, "bonemeal", 20);
|
||||
}
|
||||
else if ("qtharal_complete".equals(keyName)) addQuestProgress(player, "bonemeal", 30);
|
||||
else if ("qthoronir_complete".equals(keyName)) addQuestProgress(player, "bonemeal", 100);
|
||||
else if ("qleonid_andor".equals(keyName)) addQuestProgress(player, "andor", 10);
|
||||
else if ("qgruil_andor".equals(keyName)) addQuestProgress(player, "andor", 20);
|
||||
else if ("qgruil_andor_complete".equals(keyName)) addQuestProgress(player, "andor", 30);
|
||||
else if ("qleonid_crossglen".equals(keyName)) addQuestProgress(player, "crossglen", 1);
|
||||
else if ("qjan".equals(keyName)) addQuestProgress(player, "jan", 10);
|
||||
else if ("qjan_complete".equals(keyName)) addQuestProgress(player, "jan", 100);
|
||||
else if ("qbucus_thieves".equals(keyName)) addQuestProgress(player, "andor", 40);
|
||||
else if ("qfallhaven_derelict".equals(keyName)) addQuestProgress(player, "andor", 50);
|
||||
else if ("qfallhaven_drunk".equals(keyName)) addQuestProgress(player, "fallhavendrunk", 10);
|
||||
else if ("qfallhaven_drunk_complete".equals(keyName)) addQuestProgress(player, "fallhavendrunk", 100);
|
||||
else if ("qnocmar_unnmir".equals(keyName)) addQuestProgress(player, "nocmar", 10);
|
||||
else if ("qnocmar".equals(keyName)) addQuestProgress(player, "nocmar", 20);
|
||||
else if ("qnocmar_complete".equals(keyName)) addQuestProgress(player, "nocmar", 200);
|
||||
else if ("qfallhaven_tavern_room2".equals(keyName)) addQuestProgress(player, "fallhaventavern", 10);
|
||||
else if ("qarcir".equals(keyName)) addQuestProgress(player, "arcir", 10);
|
||||
else if ("qfallhaven_oldman".equals(keyName)) addQuestProgress(player, "calomyran", 10);
|
||||
else if ("qcalomyran_tornpage".equals(keyName)) addQuestProgress(player, "calomyran", 20);
|
||||
else if ("qfallhaven_oldman_complete".equals(keyName)) addQuestProgress(player, "calomyran", 100);
|
||||
else if ("qbucus".equals(keyName)) addQuestProgress(player, "bucus", 10);
|
||||
else if ("qthoronir_catacombs".equals(keyName)) addQuestProgress(player, "bucus", 20);
|
||||
else if ("qathamyr_complete".equals(keyName)) addQuestProgress(player, "bucus", 40);
|
||||
else if ("qfallhaven_church".equals(keyName)) addQuestProgress(player, "bucus", 50);
|
||||
else if ("qbucus_complete".equals(keyName)) addQuestProgress(player, "bucus", 100);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addQuestProgress(Player player, String questID, int progress) {
|
||||
player.addQuestProgress(new QuestProgress(questID, progress));
|
||||
}
|
||||
|
||||
public static void upgradeSavegame(Player player, WorldContext world, int fileversion) {
|
||||
|
||||
if (fileversion <= 12) {
|
||||
player.useItemCost = 5;
|
||||
player.health.max += 5;
|
||||
player.health.current += 5;
|
||||
player.baseTraits.maxHP += 5;
|
||||
}
|
||||
|
||||
if (fileversion <= 21) {
|
||||
int assignedSkillpoints = 0;
|
||||
for(SkillInfo skill : world.skills.getAllSkills()) {
|
||||
assignedSkillpoints += player.getSkillLevel(skill.id);
|
||||
}
|
||||
player.availableSkillIncreases = getExpectedNumberOfSkillpointsForLevel(player.getLevel()) - assignedSkillpoints;
|
||||
}
|
||||
|
||||
if (fileversion <= 21) {
|
||||
if (player.hasExactQuestProgress("prim_hunt", 240)) player.addQuestProgress(new QuestProgress("bwm_agent", 250));
|
||||
if (player.hasExactQuestProgress("bwm_agent", 240)) player.addQuestProgress(new QuestProgress("prim_hunt", 250));
|
||||
}
|
||||
|
||||
if (fileversion <= 27) {
|
||||
correctActorConditionsFromItemsPre0611b1(player, "bless", world, "elytharan_redeemer");
|
||||
correctActorConditionsFromItemsPre0611b1(player, "blackwater_misery", world, "bwm_dagger");
|
||||
correctActorConditionsFromItemsPre0611b1(player, "regen", world, "ring_shadow0");
|
||||
}
|
||||
|
||||
if (fileversion <= 30) {
|
||||
player.baseTraits.attackCost = Player.DEFAULT_PLAYER_ATTACKCOST;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getExpectedNumberOfSkillpointsForLevel(int level) {
|
||||
level -= Constants.FIRST_SKILL_POINT_IS_GIVEN_AT_LEVEL;
|
||||
if (level < 0) return 0;
|
||||
return 1 + (int) FloatMath.floor((float) level / Constants.NEW_SKILL_POINT_EVERY_N_LEVELS);
|
||||
}
|
||||
|
||||
private static void correctActorConditionsFromItemsPre0611b1(Player player, String conditionTypeID, WorldContext world, String itemTypeIDWithCondition) {
|
||||
if (!player.hasCondition(conditionTypeID)) return;
|
||||
boolean hasItemWithCondition = false;
|
||||
for (ItemType t : player.inventory.wear) {
|
||||
if (t == null) continue;
|
||||
if (t.effects_equip == null) continue;
|
||||
if (t.effects_equip.addedConditions == null) continue;
|
||||
for(ActorConditionEffect e : t.effects_equip.addedConditions) {
|
||||
if (!e.conditionType.conditionTypeID.equals(conditionTypeID)) continue;
|
||||
hasItemWithCondition = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasItemWithCondition) return;
|
||||
|
||||
ActorStatsController.removeConditionsFromUnequippedItem(player, world.itemTypes.getItemType(itemTypeIDWithCondition));
|
||||
}
|
||||
|
||||
public static void readCombatTraitsPreV034(DataInputStream src, int fileversion) throws IOException {
|
||||
if (fileversion >= 25) {
|
||||
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,27 +0,0 @@
|
||||
package com.gpl.rpg.AndorsTrail.view;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.R;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.ActorTraits;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
public final class BaseTraitsInfoView extends TraitsInfoView {
|
||||
private final TextView basetraitsinfo_max_hp;
|
||||
private final TextView basetraitsinfo_max_ap;
|
||||
|
||||
public BaseTraitsInfoView(Context context, AttributeSet attr) {
|
||||
super(context, attr, R.layout.basetraitsinfoview);
|
||||
|
||||
basetraitsinfo_max_hp = (TextView) findViewById(R.id.basetraitsinfo_max_hp);
|
||||
basetraitsinfo_max_ap = (TextView) findViewById(R.id.basetraitsinfo_max_ap);
|
||||
}
|
||||
|
||||
public void update(ActorTraits traits) {
|
||||
super.update(traits);
|
||||
|
||||
basetraitsinfo_max_hp.setText(Integer.toString(traits.maxHP));
|
||||
basetraitsinfo_max_ap.setText(Integer.toString(traits.maxAP));
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ public final class CombatView extends RelativeLayout {
|
||||
if (currentActiveMonster != null) {
|
||||
actionBar.setVisibility(View.INVISIBLE);
|
||||
monsterActionText.setVisibility(View.VISIBLE);
|
||||
monsterActionText.setText(res.getString(R.string.combat_monsteraction, currentActiveMonster.actorTraits.name));
|
||||
monsterActionText.setText(res.getString(R.string.combat_monsteraction, currentActiveMonster.getName()));
|
||||
} else {
|
||||
actionBar.setVisibility(View.VISIBLE);
|
||||
monsterActionText.setVisibility(View.GONE);
|
||||
@@ -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.actorTraits.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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ public final class ItemEffectsView_OnUse extends LinearLayout {
|
||||
if (t.addedConditions_source != null) sourceEffects.addAll(Arrays.asList(t.addedConditions_source));
|
||||
if (t.addedConditions_target != null) targetEffects.addAll(Arrays.asList(t.addedConditions_target));
|
||||
|
||||
describeStatsModifierTraits(t, context, res, itemeffect_onuse_list);
|
||||
describeStatsModifierTraits(t.changedStats, context, res, itemeffect_onuse_list);
|
||||
}
|
||||
}
|
||||
itemeffect_onuse_conditions_source.update(sourceEffects);
|
||||
|
||||
@@ -278,10 +278,10 @@ public final class MainView extends SurfaceView implements SurfaceHolder.Callbac
|
||||
}
|
||||
}
|
||||
|
||||
drawFromMapPosition(canvas, area, playerPosition, model.player.actorTraits.iconID);
|
||||
drawFromMapPosition(canvas, area, playerPosition, model.player.iconID);
|
||||
for (MonsterSpawnArea a : currentMap.spawnAreas) {
|
||||
for (Monster m : a.monsters) {
|
||||
drawFromMapPosition(canvas, area, m.rectPosition, m.actorTraits.iconID);
|
||||
drawFromMapPosition(canvas, area, m.rectPosition, m.iconID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public final class StatusView extends RelativeLayout {
|
||||
expBar.init(R.drawable.ui_progress_exp, R.string.status_exp);
|
||||
|
||||
levelupDrawable = new LayerDrawable(new Drawable[] {
|
||||
new BitmapDrawable(world.tileManager.preloadedTiles.getBitmap(player.actorTraits.iconID))
|
||||
new BitmapDrawable(world.tileManager.preloadedTiles.getBitmap(player.iconID))
|
||||
,new BitmapDrawable(world.tileManager.preloadedTiles.getBitmap(TileManager.iconID_moveselect))
|
||||
});
|
||||
|
||||
|
||||
@@ -1,112 +1,129 @@
|
||||
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;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TableRow;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class TraitsInfoView extends TableLayout {
|
||||
private final TableRow traitsinfo_attack_row1;
|
||||
private final TableRow traitsinfo_attack_row2;
|
||||
private final TableRow traitsinfo_attack_row3;
|
||||
private final TableRow traitsinfo_critical_row1;
|
||||
private final TableRow traitsinfo_critical_row2;
|
||||
private final TableRow traitsinfo_critical_row3;
|
||||
private final TableRow traitsinfo_defense_row1;
|
||||
private final TableRow traitsinfo_defense_row2;
|
||||
private final TextView traitsinfo_attack_cost;
|
||||
private final TextView traitsinfo_attack_chance;
|
||||
private final TextView traitsinfo_attack_damage;
|
||||
private final TextView traitsinfo_criticalhit_skill;
|
||||
private final TextView traitsinfo_criticalhit_multiplier;
|
||||
private final TextView traitsinfo_criticalhit_effectivechance;
|
||||
private final TextView traitsinfo_defense_chance;
|
||||
private final TextView traitsinfo_defense_damageresist;
|
||||
public final class TraitsInfoView {
|
||||
|
||||
public TraitsInfoView(Context context, AttributeSet attr) {
|
||||
this(context, attr, R.layout.traitsinfoview);
|
||||
public static void update(ViewGroup group, Actor actor) {
|
||||
TableLayout actorinfo_stats_table = (TableLayout) group.findViewById(R.id.actorinfo_stats_table);
|
||||
|
||||
updateTraitsTable(
|
||||
actorinfo_stats_table
|
||||
,actor.getMoveCost()
|
||||
,actor.getAttackCost()
|
||||
,actor.getAttackChance()
|
||||
,actor.getDamagePotential()
|
||||
,actor.getCriticalSkill()
|
||||
,actor.getCriticalMultiplier()
|
||||
,actor.getBlockChance()
|
||||
,actor.getDamageResistance()
|
||||
,actor.isImmuneToCriticalHits());
|
||||
|
||||
TextView actorinfo_currentconditions_title = (TextView) group.findViewById(R.id.actorinfo_currentconditions_title);
|
||||
ActorConditionList actorinfo_currentconditions = (ActorConditionList) group.findViewById(R.id.actorinfo_currentconditions);
|
||||
if (actor.conditions.isEmpty()) {
|
||||
actorinfo_currentconditions_title.setVisibility(View.GONE);
|
||||
actorinfo_currentconditions.setVisibility(View.GONE);
|
||||
} else {
|
||||
actorinfo_currentconditions_title.setVisibility(View.VISIBLE);
|
||||
actorinfo_currentconditions.setVisibility(View.VISIBLE);
|
||||
actorinfo_currentconditions.update(actor.conditions);
|
||||
}
|
||||
}
|
||||
|
||||
public TraitsInfoView(Context context, AttributeSet attr, int layoutResourceID) {
|
||||
super(context, attr);
|
||||
setFocusable(false);
|
||||
inflate(context, layoutResourceID, this);
|
||||
|
||||
traitsinfo_attack_row1 = (TableRow) findViewById(R.id.traitsinfo_attack_row1);
|
||||
traitsinfo_attack_row2 = (TableRow) findViewById(R.id.traitsinfo_attack_row2);
|
||||
traitsinfo_attack_row3 = (TableRow) findViewById(R.id.traitsinfo_attack_row3);
|
||||
traitsinfo_critical_row1 = (TableRow) findViewById(R.id.traitsinfo_critical_row1);
|
||||
traitsinfo_critical_row2 = (TableRow) findViewById(R.id.traitsinfo_critical_row2);
|
||||
traitsinfo_critical_row3 = (TableRow) findViewById(R.id.traitsinfo_critical_row3);
|
||||
traitsinfo_defense_row1 = (TableRow) findViewById(R.id.traitsinfo_defense_row1);
|
||||
traitsinfo_defense_row2 = (TableRow) findViewById(R.id.traitsinfo_defense_row2);
|
||||
traitsinfo_attack_cost = (TextView) findViewById(R.id.traitsinfo_attack_cost);
|
||||
traitsinfo_attack_chance = (TextView) findViewById(R.id.traitsinfo_attack_chance);
|
||||
traitsinfo_attack_damage = (TextView) findViewById(R.id.traitsinfo_attack_damage);
|
||||
traitsinfo_criticalhit_skill = (TextView) findViewById(R.id.traitsinfo_criticalhit_skill);
|
||||
traitsinfo_criticalhit_multiplier = (TextView) findViewById(R.id.traitsinfo_criticalhit_multiplier);
|
||||
traitsinfo_criticalhit_effectivechance = (TextView) findViewById(R.id.traitsinfo_criticalhit_effectivechance);
|
||||
traitsinfo_defense_chance = (TextView) findViewById(R.id.traitsinfo_defense_chance);
|
||||
traitsinfo_defense_damageresist = (TextView) findViewById(R.id.traitsinfo_defense_damageresist);
|
||||
}
|
||||
public static void updateTraitsTable(
|
||||
ViewGroup group
|
||||
,int moveCost
|
||||
,int attackCost
|
||||
,int attackChance
|
||||
,Range damagePotential
|
||||
,int criticalSkill
|
||||
,float criticalMultiplier
|
||||
,int blockChance
|
||||
,int damageResistance
|
||||
,boolean isImmuneToCriticalHits
|
||||
) {
|
||||
TableRow row;
|
||||
TextView tv;
|
||||
|
||||
tv = (TextView) group.findViewById(R.id.traitsinfo_move_cost);
|
||||
tv.setText(Integer.toString(moveCost));
|
||||
|
||||
tv = (TextView) group.findViewById(R.id.traitsinfo_attack_cost);
|
||||
tv.setText(Integer.toString(attackCost));
|
||||
|
||||
public void update(Actor actor) { update(actor.combatTraits, true); }
|
||||
public void update(ActorTraits actorTraits) { update(actorTraits.baseCombatTraits, true); }
|
||||
private void update(CombatTraits traits, boolean showEffectiveCriticalChance) {
|
||||
if (traits != null && traits.attackCost != 0) {
|
||||
traitsinfo_attack_row1.setVisibility(View.VISIBLE);
|
||||
traitsinfo_attack_cost.setText(Integer.toString(traits.attackCost));
|
||||
row = (TableRow) group.findViewById(R.id.traitsinfo_attack_chance_row);
|
||||
if (attackChance != 0) {
|
||||
row.setVisibility(View.VISIBLE);
|
||||
tv = (TextView) group.findViewById(R.id.traitsinfo_attack_chance);
|
||||
tv.setText(Integer.toString(attackChance) + "%");
|
||||
} else {
|
||||
traitsinfo_attack_row1.setVisibility(View.GONE);
|
||||
row.setVisibility(View.GONE);
|
||||
}
|
||||
if (traits != null && traits.hasAttackChanceEffect()) {
|
||||
traitsinfo_attack_row2.setVisibility(View.VISIBLE);
|
||||
traitsinfo_attack_chance.setText(Integer.toString(traits.attackChance) + "%");
|
||||
|
||||
row = (TableRow) group.findViewById(R.id.traitsinfo_attack_damage_row);
|
||||
if (damagePotential != null && damagePotential.max != 0) {
|
||||
row.setVisibility(View.VISIBLE);
|
||||
tv = (TextView) group.findViewById(R.id.traitsinfo_attack_damage);
|
||||
tv.setText(damagePotential.toMinMaxString());
|
||||
} else {
|
||||
traitsinfo_attack_row2.setVisibility(View.GONE);
|
||||
row.setVisibility(View.GONE);
|
||||
}
|
||||
if (traits != null && traits.hasAttackDamageEffect()) {
|
||||
traitsinfo_attack_row3.setVisibility(View.VISIBLE);
|
||||
traitsinfo_attack_damage.setText(traits.damagePotential.toMinMaxString());
|
||||
|
||||
row = (TableRow) group.findViewById(R.id.traitsinfo_criticalhit_skill_row);
|
||||
if (criticalSkill != 0) {
|
||||
row.setVisibility(View.VISIBLE);
|
||||
tv = (TextView) group.findViewById(R.id.traitsinfo_criticalhit_skill);
|
||||
tv.setText(Integer.toString(criticalSkill));
|
||||
} else {
|
||||
traitsinfo_attack_row3.setVisibility(View.GONE);
|
||||
row.setVisibility(View.GONE);
|
||||
}
|
||||
if (traits != null && traits.hasCriticalSkillEffect()) {
|
||||
traitsinfo_critical_row1.setVisibility(View.VISIBLE);
|
||||
traitsinfo_criticalhit_skill.setText(Integer.toString(traits.criticalSkill));
|
||||
|
||||
row = (TableRow) group.findViewById(R.id.traitsinfo_criticalhit_multiplier_row);
|
||||
if (criticalMultiplier != 0 && criticalMultiplier != 1) {
|
||||
row.setVisibility(View.VISIBLE);
|
||||
tv = (TextView) group.findViewById(R.id.traitsinfo_criticalhit_multiplier);
|
||||
tv.setText(Float.toString(criticalMultiplier));
|
||||
} else {
|
||||
traitsinfo_critical_row1.setVisibility(View.GONE);
|
||||
row.setVisibility(View.GONE);
|
||||
}
|
||||
if (traits != null && traits.hasCriticalMultiplierEffect()) {
|
||||
traitsinfo_critical_row2.setVisibility(View.VISIBLE);
|
||||
traitsinfo_criticalhit_multiplier.setText(Float.toString(traits.criticalMultiplier));
|
||||
|
||||
row = (TableRow) group.findViewById(R.id.traitsinfo_criticalhit_effectivechance_row);
|
||||
if (criticalSkill != 0 && criticalMultiplier != 0 && criticalMultiplier != 1) {
|
||||
row.setVisibility(View.VISIBLE);
|
||||
tv = (TextView) group.findViewById(R.id.traitsinfo_criticalhit_effectivechance);
|
||||
tv.setText(Integer.toString(Actor.getEffectiveCriticalChance(criticalSkill)) + "%");
|
||||
} else {
|
||||
traitsinfo_critical_row2.setVisibility(View.GONE);
|
||||
row.setVisibility(View.GONE);
|
||||
}
|
||||
if (showEffectiveCriticalChance && traits != null && traits.hasCriticalAttacks()) {
|
||||
traitsinfo_critical_row3.setVisibility(View.VISIBLE);
|
||||
traitsinfo_criticalhit_effectivechance.setText(Integer.toString(traits.getEffectiveCriticalChance()) + "%");
|
||||
|
||||
row = (TableRow) group.findViewById(R.id.traitsinfo_block_chance_row);
|
||||
if (blockChance != 0) {
|
||||
row.setVisibility(View.VISIBLE);
|
||||
tv = (TextView) group.findViewById(R.id.traitsinfo_block_chance);
|
||||
tv.setText(Integer.toString(blockChance) + "%");
|
||||
} else {
|
||||
traitsinfo_critical_row3.setVisibility(View.GONE);
|
||||
row.setVisibility(View.GONE);
|
||||
}
|
||||
if (traits != null && traits.hasBlockEffect()) {
|
||||
traitsinfo_defense_row1.setVisibility(View.VISIBLE);
|
||||
traitsinfo_defense_chance.setText(Integer.toString(traits.blockChance) + "%");
|
||||
|
||||
row = (TableRow) group.findViewById(R.id.traitsinfo_damageresist_row);
|
||||
if (damageResistance != 0) {
|
||||
row.setVisibility(View.VISIBLE);
|
||||
tv = (TextView) group.findViewById(R.id.traitsinfo_damageresist);
|
||||
tv.setText(Integer.toString(damageResistance));
|
||||
} else {
|
||||
traitsinfo_defense_row1.setVisibility(View.GONE);
|
||||
}
|
||||
if (traits != null && traits.damageResistance != 0) {
|
||||
traitsinfo_defense_row2.setVisibility(View.VISIBLE);
|
||||
traitsinfo_defense_damageresist.setText(Integer.toString(traits.damageResistance));
|
||||
} else {
|
||||
traitsinfo_defense_row2.setVisibility(View.GONE);
|
||||
row.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
row = (TableRow) group.findViewById(R.id.traitsinfo_is_immune_to_critical_hits_row);
|
||||
row.setVisibility(isImmuneToCriticalHits ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user