Compare commits

...

2 Commits

Author SHA1 Message Date
OMGeeky
6f2ba0fe7a naming & accidental change 2025-05-02 22:25:09 +02:00
OMGeeky
06f1a791e3 implement on-miss and on-miss-received item effects
this should allow for something like a shield, that applies an actor condition to the attacker or the player, when it successfully blocks an attack (like a generic taunt for items), but also, when the player misses with his weapon, he could get an effect (for example something like embarrassed if we stay in the direction taunt is going)
2025-05-02 22:22:36 +02:00
12 changed files with 165 additions and 47 deletions

View File

@@ -67,8 +67,10 @@ public final class ItemInfoActivity extends AndorsTrailBaseActivity {
itemType.effects_equip,
itemType.effects_use == null ? null : Collections.singletonList(itemType.effects_use),
itemType.effects_hit == null ? null : Collections.singletonList(itemType.effects_hit),
itemType.effects_miss == null ? null : Collections.singletonList(itemType.effects_miss),
itemType.effects_kill == null ? null : Collections.singletonList(itemType.effects_kill),
itemType.effects_hitReceived == null ? null : Collections.singletonList(itemType.effects_hitReceived),
itemType.effects_missReceived == null ? null : Collections.singletonList(itemType.effects_missReceived),
null,
itemType.isWeapon()
);

View File

@@ -90,8 +90,10 @@ public final class MonsterInfoActivity extends AndorsTrailBaseActivity {
null,
null,
monster.getOnHitEffectsAsList(),
monster.getOnMissEffectsAsList(),
null,
monster.getOnHitReceivedEffectsAsList(),
monster.getOnMissReceivedEffectsAsList(),
monster.getOnDeathEffects(),
false);
hp.update(monster.getMaxHP(), monster.getCurrentHP());

View File

@@ -183,19 +183,25 @@ public final class HeroinfoActivity_Stats extends Fragment {
);
ArrayList<ItemTraits_OnUse> effects_hit = new ArrayList<ItemTraits_OnUse>();
ArrayList<ItemTraits_OnUse> effects_miss = new ArrayList<ItemTraits_OnUse>();
ArrayList<ItemTraits_OnUse> effects_kill = new ArrayList<ItemTraits_OnUse>();
ArrayList<ItemTraits_OnHitReceived> effects_hitReceived = new ArrayList<ItemTraits_OnHitReceived>();
ArrayList<ItemTraits_OnHitReceived> effects_missReceived = new ArrayList<ItemTraits_OnHitReceived>();
for (Inventory.WearSlot slot : Inventory.WearSlot.values()) {
ItemType type = player.inventory.getItemTypeInWearSlot(slot);
if (type == null) continue;
if (type.effects_hit != null) effects_hit.add(type.effects_hit);
if (type.effects_miss != null) effects_miss.add(type.effects_miss);
if (type.effects_kill != null) effects_kill.add(type.effects_kill);
if (type.effects_hitReceived != null) effects_hitReceived.add(type.effects_hitReceived);
if (type.effects_missReceived != null) effects_missReceived.add(type.effects_missReceived);
}
if (effects_hit.isEmpty()) effects_hit = null;
if (effects_miss.isEmpty()) effects_miss = null;
if (effects_kill.isEmpty()) effects_kill = null;
if (effects_hitReceived.isEmpty()) effects_hitReceived = null;
actorinfo_onhiteffects.update(null, null, effects_hit, effects_kill, effects_hitReceived, null, false);
if (effects_missReceived.isEmpty()) effects_missReceived = null;
actorinfo_onhiteffects.update(null, null, effects_hit, effects_miss, effects_kill, effects_hitReceived,effects_missReceived, null, false);
updateStatsTableRow(world.model.statistics.getNumberOfCompletedQuests(world), R.id.heroinfo_gamestats_quests, R.id.heroinfo_gamestats_quests_row);

View File

@@ -595,7 +595,10 @@ public final class CombatController implements VisualEffectCompletedCallback {
private AttackResult attack(final Actor attacker, final Actor target) {
int hitChance = getAttackHitChance(attacker, target);
if (!Constants.roll100(hitChance)) return AttackResult.MISS;
if (!Constants.roll100(hitChance)) {
applyAttackMissStatusEffects(attacker, target);
return AttackResult.MISS;
}
int damage = Constants.rollValue(attacker.getDamagePotential());
boolean isCriticalHit = false;
@@ -629,6 +632,21 @@ public final class CombatController implements VisualEffectCompletedCallback {
}
}
private void applyAttackMissStatusEffects(Actor attacker, Actor target) {
ItemTraits_OnUse[] onMissEffects = attacker.getOnMissEffects();
ItemTraits_OnHitReceived[] onMissReceivedEffects = target.getOnMissReceivedEffects();
if (onMissEffects != null) {
for (ItemTraits_OnUse e : onMissEffects) {
controllers.actorStatsController.applyUseEffect(attacker, target, e);
}
}
if (onMissReceivedEffects != null) {
for (ItemTraits_OnHitReceived e : onMissReceivedEffects) {
controllers.actorStatsController.applyHitReceivedEffect(target, attacker, e);
}
}
}
public void endOfCombatRound() {
world.model.worldData.tickWorldTime();
controllers.gameRoundController.resetRoundTimers();

View File

@@ -195,19 +195,27 @@ public final class ItemController {
public static void recalculateHitEffectsFromWornItems(Player player) {
ArrayList<ItemTraits_OnUse> effects_onHit = null;
ArrayList<ItemTraits_OnUse> effects_onMiss = null;
ArrayList<ItemTraits_OnHitReceived> effects_onHitReceived = null;
ArrayList<ItemTraits_OnHitReceived> effects_onMissReceived = null;
for (Inventory.WearSlot slot : Inventory.WearSlot.values()) {
ItemType type = player.inventory.getItemTypeInWearSlot(slot);
if (type == null) continue;
ItemTraits_OnUse eh = type.effects_hit;
ItemTraits_OnHitReceived ehr = type.effects_hitReceived;
if (eh == null && ehr == null) continue;
ItemTraits_OnUse em = type.effects_miss;
ItemTraits_OnHitReceived emr = type.effects_missReceived;
if (eh == null && ehr == null && em == null && emr == null) continue;
if (effects_onHit == null) effects_onHit = new ArrayList<ItemTraits_OnUse>();
if (eh != null) effects_onHit.add(eh);
if (effects_onMiss == null) effects_onMiss = new ArrayList<ItemTraits_OnUse>();
if (em != null) effects_onMiss.add(em);
if (effects_onHitReceived == null) effects_onHitReceived = new ArrayList<ItemTraits_OnHitReceived>();
if (ehr != null) effects_onHitReceived.add(ehr);
if (effects_onMissReceived == null) effects_onMissReceived = new ArrayList<ItemTraits_OnHitReceived>();
if (emr != null) effects_onMissReceived.add(emr);
}
if (effects_onHit != null) {
@@ -217,6 +225,13 @@ public final class ItemController {
} else {
player.onHitEffects = null;
}
if (effects_onMiss != null) {
ItemTraits_OnUse[] effects_ = new ItemTraits_OnUse[effects_onMiss.size()];
effects_ = effects_onMiss.toArray(effects_);
player.onMissEffects = effects_;
} else {
player.onMissEffects = null;
}
if (effects_onHitReceived != null) {
ItemTraits_OnHitReceived[] effects_ = new ItemTraits_OnHitReceived[effects_onHitReceived.size()];
@@ -225,6 +240,13 @@ public final class ItemController {
} else {
player.onHitReceivedEffects = null;
}
if (effects_onMissReceived != null) {
ItemTraits_OnHitReceived[] effects_ = new ItemTraits_OnHitReceived[effects_onMissReceived.size()];
effects_ = effects_onMissReceived.toArray(effects_);
player.onMissReceivedEffects = effects_;
} else {
player.onMissReceivedEffects = null;
}
}
public void consumeNonItemLoot(Loot loot) {

View File

@@ -35,7 +35,9 @@ public class Actor {
public int blockChance;
public int damageResistance;
public ItemTraits_OnUse[] onHitEffects;
public ItemTraits_OnUse[] onMissEffects;
public ItemTraits_OnHitReceived[] onHitReceivedEffects;
public ItemTraits_OnHitReceived[] onMissReceivedEffects;
public ItemTraits_OnUse onDeathEffects;
public boolean hasVFXRunning = false;
public long vfxStartTime = 0;
@@ -69,8 +71,12 @@ public class Actor {
public int getDamageResistance() { return damageResistance; }
public ItemTraits_OnUse[] getOnHitEffects() { return onHitEffects; }
public List<ItemTraits_OnUse> getOnHitEffectsAsList() { return onHitEffects == null ? null : Arrays.asList(onHitEffects); }
public ItemTraits_OnUse[] getOnMissEffects() { return onMissEffects; }
public List<ItemTraits_OnUse> getOnMissEffectsAsList() { return onMissEffects == null ? null : Arrays.asList(onMissEffects); }
public ItemTraits_OnHitReceived[] getOnHitReceivedEffects() { return onHitReceivedEffects; }
public List<ItemTraits_OnHitReceived> getOnHitReceivedEffectsAsList() { return onHitReceivedEffects == null ? null : Arrays.asList(onHitReceivedEffects); }
public ItemTraits_OnHitReceived[] getOnMissReceivedEffects() { return onMissReceivedEffects; }
public List<ItemTraits_OnHitReceived> getOnMissReceivedEffectsAsList() { return onMissReceivedEffects == null ? null : Arrays.asList(onMissReceivedEffects); }
public ItemTraits_OnUse getOnDeathEffects() { return onDeathEffects; }
public boolean hasCriticalSkillEffect() { return getCriticalSkill() != 0; }

View File

@@ -33,8 +33,10 @@ public final class ItemType {
public final ItemTraits_OnEquip effects_equip;
public final ItemTraits_OnUse effects_use;
public final ItemTraits_OnUse effects_hit;
public final ItemTraits_OnUse effects_miss;
public final ItemTraits_OnUse effects_kill;
public final ItemTraits_OnHitReceived effects_hitReceived;
public final ItemTraits_OnHitReceived effects_missReceived;
public ItemType(
String id
@@ -48,8 +50,10 @@ public final class ItemType {
, ItemTraits_OnEquip effects_equip
, ItemTraits_OnUse effects_use
, ItemTraits_OnUse effects_hit
, ItemTraits_OnUse effects_miss
, ItemTraits_OnUse effects_kill
, ItemTraits_OnHitReceived effects_hitReceived
, ItemTraits_OnHitReceived effects_missReceived
) {
this.id = id;
this.iconID = iconID;
@@ -63,8 +67,10 @@ public final class ItemType {
this.effects_equip = effects_equip;
this.effects_use = effects_use;
this.effects_hit = effects_hit;
this.effects_miss = effects_miss;
this.effects_kill = effects_kill;
this.effects_hitReceived = effects_hitReceived;
this.effects_missReceived = effects_missReceived;
this.hasPersonalizedName = name.contains(Constants.PLACEHOLDER_PLAYERNAME);
}

View File

@@ -41,9 +41,11 @@ public final class ItemTypeParser extends JsonCollectionParserFor<ItemType> {
final ItemTraits_OnEquip equipEffect = itemTraitsParser.parseItemTraits_OnEquip(o.optJSONObject(JsonFieldNames.ItemType.equipEffect));
final ItemTraits_OnUse useEffect = itemTraitsParser.parseItemTraits_OnUse(o.optJSONObject(JsonFieldNames.ItemType.useEffect));
final ItemTraits_OnUse hitEffect = itemTraitsParser.parseItemTraits_OnUse(o.optJSONObject(JsonFieldNames.ItemType.hitEffect));
final ItemTraits_OnUse missEffect = itemTraitsParser.parseItemTraits_OnUse(o.optJSONObject(JsonFieldNames.ItemType.missEffect));
final ItemTraits_OnUse killEffect = itemTraitsParser.parseItemTraits_OnUse(o.optJSONObject(JsonFieldNames.ItemType.killEffect));
final ItemTraits_OnHitReceived hitReceivedEffect = itemTraitsParser.parseItemTraits_OnHitReceived(o.optJSONObject(JsonFieldNames.ItemType.hitReceivedEffect));
final ItemTraits_OnHitReceived missReceivedEffect = itemTraitsParser.parseItemTraits_OnHitReceived(o.optJSONObject(JsonFieldNames.ItemType.missReceivedEffect));
final int baseMarketCost = o.optInt(JsonFieldNames.ItemType.baseMarketCost);
final boolean hasManualPrice = o.optInt(JsonFieldNames.ItemType.hasManualPrice, 0) > 0;
final ItemType itemType = new ItemType(
@@ -58,8 +60,10 @@ public final class ItemTypeParser extends JsonCollectionParserFor<ItemType> {
, equipEffect
, useEffect
, hitEffect
, missEffect
, killEffect
, hitReceivedEffect
, missReceivedEffect
);
return new Pair<String, ItemType>(id, itemType);
}

View File

@@ -167,8 +167,10 @@ public final class JsonFieldNames {
public static final String equipEffect = "equipEffect";
public static final String useEffect = "useEffect";
public static final String hitEffect = "hitEffect";
public static final String missEffect = "missEffect";
public static final String killEffect = "killEffect";
public static final String hitReceivedEffect = "hitReceivedEffect";
public static final String missReceivedEffect = "missReceivedEffect";
}

View File

@@ -20,13 +20,17 @@ public final class ItemEffectsView extends LinearLayout {
private final ActorConditionEffectList itemeffect_onequip_conditions;
private final ItemEffectsView_OnUse itemeffect_onuse;
private final ItemEffectsView_OnUse itemeffect_onhit;
private final ItemEffectsView_OnUse itemeffect_onmiss;
private final ItemEffectsView_OnUse itemeffect_onkill;
private final ItemEffectsView_OnHitReceived itemeffect_onhitreceived;
private final ItemEffectsView_OnHitReceived itemeffect_onmissreceived;
private final ItemEffectsView_OnDeath itemeffect_ondeath;
private final TextView itemeffect_onuse_title;
private final TextView itemeffect_onhit_title;
private final TextView itemeffect_onmiss_title;
private final TextView itemeffect_onkill_title;
private final TextView itemeffect_onhitreceived_title;
private final TextView itemeffect_onmissreceived_title;
private final TextView itemeffect_ondeath_title;
public ItemEffectsView(Context context, AttributeSet attr) {
@@ -41,13 +45,17 @@ public final class ItemEffectsView extends LinearLayout {
itemeffect_onuse = (ItemEffectsView_OnUse) findViewById(R.id.itemeffect_onuse);
itemeffect_onhit = (ItemEffectsView_OnUse) findViewById(R.id.itemeffect_onhit);
itemeffect_onmiss = (ItemEffectsView_OnUse) findViewById(R.id.itemeffect_onmiss);
itemeffect_onkill = (ItemEffectsView_OnUse) findViewById(R.id.itemeffect_onkill);
itemeffect_onhitreceived = (ItemEffectsView_OnHitReceived) findViewById(R.id.itemeffect_onhitreceived);
itemeffect_onmissreceived = (ItemEffectsView_OnHitReceived) findViewById(R.id.itemeffect_onmissreceived);
itemeffect_ondeath = (ItemEffectsView_OnDeath) findViewById(R.id.itemeffect_ondeath);
itemeffect_onuse_title = (TextView) findViewById(R.id.itemeffect_onuse_title);
itemeffect_onhit_title = (TextView) findViewById(R.id.itemeffect_onhit_title);
itemeffect_onmiss_title = (TextView) findViewById(R.id.itemeffect_onmiss_title);
itemeffect_onkill_title = (TextView) findViewById(R.id.itemeffect_onkill_title);
itemeffect_onhitreceived_title = (TextView) findViewById(R.id.itemeffect_onhitreceived_title);
itemeffect_onmissreceived_title = (TextView) findViewById(R.id.itemeffect_onmissreceived_title);
itemeffect_ondeath_title = (TextView) findViewById(R.id.itemeffect_ondeath_title);
}
@@ -55,8 +63,10 @@ public final class ItemEffectsView extends LinearLayout {
ItemTraits_OnEquip effects_equip,
Collection<ItemTraits_OnUse> effects_use,
Collection<ItemTraits_OnUse> effects_hit,
Collection<ItemTraits_OnUse> effects_miss,
Collection<ItemTraits_OnUse> effects_kill,
Collection<ItemTraits_OnHitReceived> effects_hitreceived,
Collection<ItemTraits_OnHitReceived> effects_missreceived,
ItemTraits_OnUse effects_death,
boolean isWeapon
) {
@@ -90,6 +100,12 @@ public final class ItemEffectsView extends LinearLayout {
} else {
itemeffect_onhit_title.setVisibility(View.GONE);
}
itemeffect_onmiss.update(effects_miss);
if (effects_miss != null) {
itemeffect_onmiss_title.setVisibility(View.VISIBLE);
} else {
itemeffect_onmiss_title.setVisibility(View.GONE);
}
itemeffect_onkill.update(effects_kill);
if (effects_kill != null) {
@@ -104,6 +120,12 @@ public final class ItemEffectsView extends LinearLayout {
} else {
itemeffect_onhitreceived_title.setVisibility(View.GONE);
}
itemeffect_onmissreceived.update(effects_missreceived);
if (effects_missreceived != null) {
itemeffect_onmissreceived_title.setVisibility(View.VISIBLE);
} else {
itemeffect_onmissreceived_title.setVisibility(View.GONE);
}
itemeffect_ondeath.update(effects_death);
if (effects_death != null) {

View File

@@ -12,19 +12,19 @@
android:layout_height="wrap_content"
/>
<com.gpl.rpg.AndorsTrail.view.AbilityModifierInfoView
android:id="@+id/itemeffect_onequip_abilitymodifierinfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<com.gpl.rpg.AndorsTrail.view.AbilityModifierInfoView
android:id="@+id/itemeffect_onequip_abilitymodifierinfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<com.gpl.rpg.AndorsTrail.view.ActorConditionEffectList
android:id="@+id/itemeffect_onequip_conditions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<com.gpl.rpg.AndorsTrail.view.ActorConditionEffectList
android:id="@+id/itemeffect_onequip_conditions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<TextView
android:text="@string/iteminfo_effect_works_when_used"
@@ -32,12 +32,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView_OnUse
android:id="@+id/itemeffect_onuse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView_OnUse
android:id="@+id/itemeffect_onuse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<TextView
android:text="@string/iteminfo_effect_works_when_hitting_target"
@@ -45,12 +45,25 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView_OnUse
android:id="@+id/itemeffect_onhit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView_OnUse
android:id="@+id/itemeffect_onhit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<TextView
android:text="@string/iteminfo_effect_works_when_missing_target"
android:id="@+id/itemeffect_onmiss_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView_OnUse
android:id="@+id/itemeffect_onmiss"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<TextView
android:text="@string/iteminfo_effect_works_when_killing_target"
@@ -58,12 +71,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView_OnUse
android:id="@+id/itemeffect_onkill"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView_OnUse
android:id="@+id/itemeffect_onkill"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<TextView
android:text="@string/iteminfo_effect_works_when_hit_by_attacker"
@@ -71,23 +84,36 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView_OnHitReceived
android:id="@+id/itemeffect_onhitreceived"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView_OnHitReceived
android:id="@+id/itemeffect_onhitreceived"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<TextView
android:text="@string/iteminfo_effect_works_when_missed_by_attacker"
android:id="@+id/itemeffect_onmissreceived_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView_OnHitReceived
android:id="@+id/itemeffect_onmissreceived"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<TextView
android:text="@string/iteminfo_effect_works_when_killed_by_attacker"
android:id="@+id/itemeffect_ondeath_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView_OnDeath
android:id="@+id/itemeffect_ondeath"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
<com.gpl.rpg.AndorsTrail.view.ItemEffectsView_OnDeath
android:id="@+id/itemeffect_ondeath"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
/>
</merge>

View File

@@ -348,10 +348,12 @@
<string name="iteminfo_effect_works_on_target">On target</string>
<string name="iteminfo_effect_works_on_attacker">On attacker</string>
<string name="iteminfo_effect_works_when_hitting_target">When hitting target</string>
<string name="iteminfo_effect_works_when_missing_target">When missing target</string>
<string name="iteminfo_effect_works_when_killing_target">On every kill</string>
<string name="iteminfo_effect_works_when_used">When used</string>
<string name="iteminfo_effect_works_when_equipped">When equipped</string>
<string name="iteminfo_effect_works_when_hit_by_attacker">When hit by attacker</string>
<string name="iteminfo_effect_works_when_missed_by_attacker">When missed by attacker</string>
<string name="iteminfo_effect_works_when_killed_by_attacker">When killed by attacker</string>
<string name="iteminfo_effect_decrease_current_hp">Drains %1$s HP</string>