mirror of
https://github.com/OMGeeky/andors-trail.git
synced 2026-01-19 10:04:52 +01:00
Merge branch 'conditions'
This commit is contained in:
8
AndorsTrail/res/anim/hidecombatbar.xml
Normal file
8
AndorsTrail/res/anim/hidecombatbar.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<translate
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:duration="300"
|
||||
android:fromYDelta="0%"
|
||||
android:toYDelta="-100%"
|
||||
/>
|
||||
28
AndorsTrail/res/anim/scalebeat.xml
Normal file
28
AndorsTrail/res/anim/scalebeat.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
>
|
||||
|
||||
<scale
|
||||
android:fromXScale="1.0"
|
||||
android:fromYScale="1.0"
|
||||
android:toXScale="1.1"
|
||||
android:toYScale="1.1"
|
||||
android:duration="100"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
android:interpolator="@android:anim/decelerate_interpolator"
|
||||
/>
|
||||
<scale
|
||||
android:fromXScale="1.1"
|
||||
android:fromYScale="1.1"
|
||||
android:toXScale="1.0"
|
||||
android:toYScale="1.0"
|
||||
android:duration="100"
|
||||
android:startOffset="100"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
/>
|
||||
</set>
|
||||
12
AndorsTrail/res/anim/scaledown.xml
Normal file
12
AndorsTrail/res/anim/scaledown.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<scale
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:fromXScale="1.0"
|
||||
android:fromYScale="1.0"
|
||||
android:toXScale="0.0"
|
||||
android:toYScale="0.0"
|
||||
android:duration="300"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
/>
|
||||
12
AndorsTrail/res/anim/scaleup.xml
Normal file
12
AndorsTrail/res/anim/scaleup.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<scale
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:interpolator="@android:anim/overshoot_interpolator"
|
||||
android:fromXScale="0.0"
|
||||
android:fromYScale="0.0"
|
||||
android:toXScale="1.0"
|
||||
android:toYScale="1.0"
|
||||
android:duration="200"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
/>
|
||||
8
AndorsTrail/res/anim/showcombatbar.xml
Normal file
8
AndorsTrail/res/anim/showcombatbar.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<translate
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:interpolator="@android:anim/decelerate_interpolator"
|
||||
android:duration="300"
|
||||
android:fromYDelta="-100%"
|
||||
android:toYDelta="0%"
|
||||
/>
|
||||
@@ -54,13 +54,12 @@
|
||||
android:shadowColor="#000"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/main_statusview"
|
||||
android:layout_margin="5dp"
|
||||
android:id="@+id/statusview_activeconditions"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="right"
|
||||
/>
|
||||
|
||||
|
||||
@@ -504,5 +504,8 @@
|
||||
<string name="skill_longdescription_concussion">When making an attack on a target whose block chance (BC) is at least %1$d lower than your attack chance (AC), there is a %2$d %% chance that the hit will cause a concussion on the target. A concussion will severely lower the target\'s offensive combat abilities, making the target less able to land successful attacks.</string>
|
||||
|
||||
<string name="about_button4">About</string>
|
||||
<string name="preferences_ui_category">Interface</string>
|
||||
<string name="preferences_ui_enable_animations_title">Enable animations</string>
|
||||
<string name="preferences_ui_enable_animations">Show animations for various interface elements, such as the combat bar.</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -72,4 +72,12 @@
|
||||
android:summary="@string/preferences_movement_dpad_minimizeable"
|
||||
android:key="dpadMinimizeable" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
android:title="@string/preferences_ui_category">
|
||||
<CheckBoxPreference
|
||||
android:title="@string/preferences_ui_enable_animations_title"
|
||||
android:defaultValue="true"
|
||||
android:summary="@string/preferences_ui_enable_animations"
|
||||
android:key="enableUiAnimations" />
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -34,6 +34,7 @@ public class AndorsTrailPreferences {
|
||||
public int dpadPosition;
|
||||
public boolean dpadMinimizeable = true;
|
||||
public boolean optimizedDrawing = false;
|
||||
public boolean enableUiAnimations = true;
|
||||
|
||||
public static void read(final Context androidContext, AndorsTrailPreferences dest) {
|
||||
try {
|
||||
@@ -48,6 +49,7 @@ public class AndorsTrailPreferences {
|
||||
dest.dpadPosition = Integer.parseInt(prefs.getString("dpadposition", Integer.toString(DPAD_POSITION_DISABLED)));
|
||||
dest.dpadMinimizeable = prefs.getBoolean("dpadMinimizeable", true);
|
||||
dest.optimizedDrawing = prefs.getBoolean("optimized_drawing", false);
|
||||
dest.enableUiAnimations = prefs.getBoolean("enableUiAnimations", true);
|
||||
|
||||
// This might be implemented as a skill in the future.
|
||||
//dest.movementAggressiveness = Integer.parseInt(prefs.getString("movementaggressiveness", Integer.toString(MOVEMENTAGGRESSIVENESS_NORMAL)));
|
||||
@@ -63,6 +65,7 @@ public class AndorsTrailPreferences {
|
||||
dest.dpadPosition = DPAD_POSITION_DISABLED;
|
||||
dest.dpadMinimizeable = true;
|
||||
dest.optimizedDrawing = false;
|
||||
dest.enableUiAnimations = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.gpl.rpg.AndorsTrail.model.actor.Player;
|
||||
import com.gpl.rpg.AndorsTrail.model.item.ItemContainer.ItemEntry;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
import com.gpl.rpg.AndorsTrail.view.CombatView;
|
||||
import com.gpl.rpg.AndorsTrail.view.DisplayActiveActorConditionIcons;
|
||||
import com.gpl.rpg.AndorsTrail.view.MainView;
|
||||
import com.gpl.rpg.AndorsTrail.view.VirtualDpadView;
|
||||
import com.gpl.rpg.AndorsTrail.view.QuickButton.QuickButtonContextMenuInfo;
|
||||
@@ -33,7 +34,7 @@ import android.view.View;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.MenuItem.OnMenuItemClickListener;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
@@ -59,7 +60,7 @@ public final class MainActivity extends Activity {
|
||||
public StatusView statusview;
|
||||
public CombatView combatview;
|
||||
public QuickitemView quickitemview;
|
||||
private LinearLayout activeConditions;
|
||||
private DisplayActiveActorConditionIcons activeConditions;
|
||||
private VirtualDpadView dpad;
|
||||
|
||||
private static final int NUM_MESSAGES = 3;
|
||||
@@ -84,7 +85,7 @@ public final class MainActivity extends Activity {
|
||||
statusview = (StatusView) findViewById(R.id.main_statusview);
|
||||
combatview = (CombatView) findViewById(R.id.main_combatview);
|
||||
quickitemview = (QuickitemView) findViewById(R.id.main_quickitemview);
|
||||
activeConditions = (LinearLayout) findViewById(R.id.statusview_activeconditions);
|
||||
activeConditions = new DisplayActiveActorConditionIcons(app.preferences, world.tileManager, this, (RelativeLayout) findViewById(R.id.statusview_activeconditions));
|
||||
dpad = (VirtualDpadView) findViewById(R.id.main_virtual_dpad);
|
||||
|
||||
statusText = (TextView) findViewById(R.id.statusview_statustext);
|
||||
@@ -165,6 +166,8 @@ public final class MainActivity extends Activity {
|
||||
view.gameRoundController.pause();
|
||||
view.movementController.stopMovement();
|
||||
|
||||
activeConditions.unsubscribe(world);
|
||||
|
||||
save(Savegames.SLOT_QUICKSAVE);
|
||||
}
|
||||
|
||||
@@ -173,6 +176,8 @@ public final class MainActivity extends Activity {
|
||||
super.onResume();
|
||||
if (!AndorsTrailApplication.getApplicationFromActivity(this).setup.isSceneReady) return;
|
||||
|
||||
activeConditions.subscribe(world);
|
||||
|
||||
view.gameRoundController.resume();
|
||||
|
||||
if (world.model.uiSelections.isInCombat) {
|
||||
@@ -257,7 +262,6 @@ public final class MainActivity extends Activity {
|
||||
|
||||
public void updateStatus() {
|
||||
statusview.updateStatus();
|
||||
statusview.updateActiveConditions(this, activeConditions);
|
||||
quickitemview.refreshQuickitems();
|
||||
combatview.updateStatus();
|
||||
}
|
||||
|
||||
@@ -59,10 +59,12 @@ public class ActorStatsController {
|
||||
if (!type.conditionTypeID.equals(c.conditionType.conditionTypeID)) continue;
|
||||
if (c.duration != duration) continue;
|
||||
|
||||
actor.conditions.remove(i);
|
||||
magnitude = c.magnitude - magnitude;
|
||||
if (magnitude > 0) {
|
||||
actor.conditions.add(new ActorCondition(type, magnitude, duration));
|
||||
if (c.magnitude > magnitude) {
|
||||
c.magnitude -= magnitude;
|
||||
actor.conditionListener.onActorConditionMagnitudeChanged(actor, c);
|
||||
} else {
|
||||
actor.conditions.remove(i);
|
||||
actor.conditionListener.onActorConditionRemoved(actor, c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -109,12 +111,14 @@ public class ActorStatsController {
|
||||
if (!type.conditionTypeID.equals(c.conditionType.conditionTypeID)) continue;
|
||||
if (c.duration == duration) {
|
||||
// If the actor already has a condition of this type and the same duration, just increase the magnitude instead.
|
||||
actor.conditions.remove(i);
|
||||
magnitude += c.magnitude;
|
||||
break;
|
||||
c.magnitude += magnitude;
|
||||
actor.conditionListener.onActorConditionMagnitudeChanged(actor, c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
actor.conditions.add(new ActorCondition(type, magnitude, duration));
|
||||
ActorCondition c = new ActorCondition(type, magnitude, duration);
|
||||
actor.conditions.add(c);
|
||||
actor.conditionListener.onActorConditionAdded(actor, c);
|
||||
}
|
||||
private static void addNonStackableActorCondition(Actor actor, ActorConditionEffect e, int duration) {
|
||||
final ActorConditionType type = e.conditionType;
|
||||
@@ -123,24 +127,34 @@ public class ActorStatsController {
|
||||
ActorCondition c = actor.conditions.get(i);
|
||||
if (!type.conditionTypeID.equals(c.conditionType.conditionTypeID)) continue;
|
||||
if (c.magnitude > e.magnitude) return;
|
||||
else if (c.magnitude == e.magnitude) {
|
||||
if (c.duration >= duration) return;
|
||||
}
|
||||
// If the actor already has this condition, but of a lower magnitude, we remove the old one and add this higher magnitude.
|
||||
actor.conditions.remove(i);
|
||||
actor.conditionListener.onActorConditionRemoved(actor, c);
|
||||
}
|
||||
actor.conditions.add(e.createCondition(duration));
|
||||
|
||||
ActorCondition c = e.createCondition(duration);
|
||||
actor.conditions.add(c);
|
||||
actor.conditionListener.onActorConditionAdded(actor, c);
|
||||
}
|
||||
|
||||
public static void removeAllTemporaryConditions(final Actor actor) {
|
||||
for(int i = actor.conditions.size() - 1; i >= 0; --i) {
|
||||
if (!actor.conditions.get(i).isTemporaryEffect()) continue;
|
||||
ActorCondition c = actor.conditions.get(i);
|
||||
if (!c.isTemporaryEffect()) continue;
|
||||
actor.conditions.remove(i);
|
||||
actor.conditionListener.onActorConditionRemoved(actor, c);
|
||||
}
|
||||
}
|
||||
|
||||
private static void removeAllConditionsOfType(final Actor actor, final String conditionTypeID) {
|
||||
for(int i = actor.conditions.size() - 1; i >= 0; --i) {
|
||||
if (actor.conditions.get(i).conditionType.conditionTypeID.equals(conditionTypeID)) {
|
||||
actor.conditions.remove(i);
|
||||
}
|
||||
ActorCondition c = actor.conditions.get(i);
|
||||
if (!c.conditionType.conditionTypeID.equals(conditionTypeID)) continue;
|
||||
actor.conditions.remove(i);
|
||||
actor.conditionListener.onActorConditionRemoved(actor, c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,10 +224,13 @@ public class ActorStatsController {
|
||||
if (SkillController.rollForSkillChance(player, SkillCollection.SKILL_REJUVENATION, SkillCollection.PER_SKILLPOINT_INCREASE_REJUVENATION_CHANCE)) {
|
||||
int i = getRandomConditionForRejuvenate(player);
|
||||
if (i >= 0) {
|
||||
ActorCondition c = player.conditions.remove(i);
|
||||
ActorCondition c = player.conditions.get(i);
|
||||
if (c.magnitude > 1) {
|
||||
int magnitude = c.magnitude - 1;
|
||||
player.conditions.add(i, new ActorCondition(c.conditionType, magnitude, c.duration));
|
||||
c.magnitude -= 1;
|
||||
player.conditionListener.onActorConditionMagnitudeChanged(player, c);
|
||||
} else {
|
||||
player.conditions.remove(i);
|
||||
player.conditionListener.onActorConditionRemoved(player, c);
|
||||
}
|
||||
recalculateActorCombatTraits(player);
|
||||
}
|
||||
@@ -258,6 +275,7 @@ public class ActorStatsController {
|
||||
for (ActorCondition c : actor.conditions) {
|
||||
StatsModifierTraits effect = isFullRound ? c.conditionType.statsEffect_everyFullRound : c.conditionType.statsEffect_everyRound;
|
||||
effectToStart = applyStatsModifierEffect(actor, effect, c.magnitude, effectToStart);
|
||||
if (effect != null) actor.conditionListener.onActorConditionRoundEffectApplied(actor, c);
|
||||
}
|
||||
startVisualEffect(actor, effectToStart);
|
||||
}
|
||||
@@ -267,10 +285,13 @@ public class ActorStatsController {
|
||||
for(int i = actor.conditions.size() - 1; i >= 0; --i) {
|
||||
ActorCondition c = actor.conditions.get(i);
|
||||
if (!c.isTemporaryEffect()) continue;
|
||||
c.duration -= 1;
|
||||
if (c.duration <= 0) {
|
||||
if (c.duration <= 1) {
|
||||
actor.conditions.remove(i);
|
||||
actor.conditionListener.onActorConditionRemoved(actor, c);
|
||||
removedAnyConditions = true;
|
||||
} else {
|
||||
c.duration -= 1;
|
||||
actor.conditionListener.onActorConditionDurationChanged(actor, c);
|
||||
}
|
||||
}
|
||||
if (removedAnyConditions) {
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.content.res.Resources;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.FloatMath;
|
||||
import android.view.View;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences;
|
||||
import com.gpl.rpg.AndorsTrail.Dialogs;
|
||||
@@ -49,8 +48,7 @@ public final class CombatController implements VisualEffectCompletedCallback {
|
||||
public static final int BEGIN_TURN_CONTINUE = 2;
|
||||
|
||||
public void enterCombat(int beginTurnAs) {
|
||||
context.mainActivity.combatview.setVisibility(View.VISIBLE);
|
||||
context.mainActivity.combatview.bringToFront();
|
||||
context.mainActivity.combatview.show();
|
||||
model.uiSelections.isInCombat = true;
|
||||
killedMonsterBags.clear();
|
||||
context.mainActivity.clearMessages();
|
||||
@@ -61,7 +59,7 @@ public final class CombatController implements VisualEffectCompletedCallback {
|
||||
}
|
||||
public void exitCombat(boolean pickupLootBags) {
|
||||
setCombatSelection(null, null);
|
||||
context.mainActivity.combatview.setVisibility(View.GONE);
|
||||
context.mainActivity.combatview.hide();
|
||||
model.uiSelections.isInCombat = false;
|
||||
context.mainActivity.clearMessages();
|
||||
currentActiveMonster = null;
|
||||
|
||||
@@ -241,16 +241,12 @@ public final class MovementController implements TimedMessageTask.Callback {
|
||||
if (!world.model.currentMap.isWalkable(world.model.player.position)) {
|
||||
// If the player somehow spawned on an unwalkable tile, we move the player to the first mapchange area.
|
||||
// This could happen if we change some tile to non-walkable in a future version.
|
||||
MapObject dest = null;
|
||||
for (MapObject o : model.currentMap.eventObjects) {
|
||||
if (o.type == MapObject.MAPEVENT_NEWMAP) {
|
||||
dest = o;
|
||||
model.player.position.set(o.position.topLeft);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dest != null) {
|
||||
model.player.position.set(dest.position.topLeft);
|
||||
}
|
||||
}
|
||||
|
||||
// If any monsters somehow spawned on an unwalkable tile, we move the monster to a new position on the spawnarea
|
||||
|
||||
@@ -11,7 +11,7 @@ public class ActorCondition {
|
||||
public static final int DURATION_FOREVER = 999;
|
||||
|
||||
public final ActorConditionType conditionType;
|
||||
public final int magnitude;
|
||||
public int magnitude;
|
||||
public int duration;
|
||||
|
||||
public ActorCondition(ActorConditionType conditionType, int magnitude, int duration) {
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.util.ArrayList;
|
||||
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.listeners.ActorConditionListeners;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
import com.gpl.rpg.AndorsTrail.util.CoordRect;
|
||||
import com.gpl.rpg.AndorsTrail.util.Range;
|
||||
@@ -20,6 +21,7 @@ public class Actor {
|
||||
public final Coord position;
|
||||
public final CoordRect rectPosition;
|
||||
public final ArrayList<ActorCondition> conditions = new ArrayList<ActorCondition>();
|
||||
public final ActorConditionListeners conditionListener = new ActorConditionListeners();
|
||||
public final boolean isPlayer;
|
||||
public final boolean isImmuneToCriticalHits;
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.gpl.rpg.AndorsTrail.model.listeners;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Actor;
|
||||
|
||||
public interface ActorConditionListener {
|
||||
public void onActorConditionAdded(Actor actor, ActorCondition condition);
|
||||
public void onActorConditionRemoved(Actor actor, ActorCondition condition);
|
||||
public void onActorConditionDurationChanged(Actor actor, ActorCondition condition);
|
||||
public void onActorConditionMagnitudeChanged(Actor actor, ActorCondition condition);
|
||||
public void onActorConditionRoundEffectApplied(Actor actor, ActorCondition condition);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.gpl.rpg.AndorsTrail.model.listeners;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Actor;
|
||||
|
||||
public class ActorConditionListeners extends ListOfListeners<ActorConditionListener> implements ActorConditionListener {
|
||||
|
||||
private final Function2<ActorConditionListener, Actor, ActorCondition> onActorConditionAdded = new Function2<ActorConditionListener, Actor, ActorCondition>() {
|
||||
@Override public void call(ActorConditionListener listener, Actor actor, ActorCondition condition) { listener.onActorConditionAdded(actor, condition); }
|
||||
};
|
||||
private final Function2<ActorConditionListener, Actor, ActorCondition> onActorConditionRemoved = new Function2<ActorConditionListener, Actor, ActorCondition>() {
|
||||
@Override public void call(ActorConditionListener listener, Actor actor, ActorCondition condition) { listener.onActorConditionRemoved(actor, condition); }
|
||||
};
|
||||
private final Function2<ActorConditionListener, Actor, ActorCondition> onActorConditionDurationChanged = new Function2<ActorConditionListener, Actor, ActorCondition>() {
|
||||
@Override public void call(ActorConditionListener listener, Actor actor, ActorCondition condition) { listener.onActorConditionDurationChanged(actor, condition); }
|
||||
};
|
||||
private final Function2<ActorConditionListener, Actor, ActorCondition> onActorConditionMagnitudeChanged = new Function2<ActorConditionListener, Actor, ActorCondition>() {
|
||||
@Override public void call(ActorConditionListener listener, Actor actor, ActorCondition condition) { listener.onActorConditionMagnitudeChanged(actor, condition); }
|
||||
};
|
||||
private final Function2<ActorConditionListener, Actor, ActorCondition> onActorConditionRoundEffectApplied = new Function2<ActorConditionListener, Actor, ActorCondition>() {
|
||||
@Override public void call(ActorConditionListener listener, Actor actor, ActorCondition condition) { listener.onActorConditionRoundEffectApplied(actor, condition); }
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onActorConditionAdded(Actor actor, ActorCondition condition) {
|
||||
callAllListeners(this.onActorConditionAdded, actor, condition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActorConditionRemoved(Actor actor, ActorCondition condition) {
|
||||
callAllListeners(this.onActorConditionRemoved, actor, condition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActorConditionDurationChanged(Actor actor, ActorCondition condition) {
|
||||
callAllListeners(this.onActorConditionDurationChanged, actor, condition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActorConditionMagnitudeChanged(Actor actor, ActorCondition condition) {
|
||||
callAllListeners(this.onActorConditionMagnitudeChanged, actor, condition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActorConditionRoundEffectApplied(Actor actor, ActorCondition condition) {
|
||||
callAllListeners(this.onActorConditionRoundEffectApplied, actor, condition);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.gpl.rpg.AndorsTrail.model.listeners;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
|
||||
public class ListOfListeners<T> {
|
||||
private final ArrayList<WeakReference<T>> listeners = new ArrayList<WeakReference<T>>();
|
||||
|
||||
public void add(T listener) {
|
||||
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
|
||||
for (WeakReference<T> ref : listeners) {
|
||||
if (ref.get() == listener) {
|
||||
throw new IndexOutOfBoundsException("FAIL: listener added twice to ListOfListeners.");
|
||||
}
|
||||
}
|
||||
}
|
||||
listeners.add(new WeakReference<T>(listener));
|
||||
}
|
||||
public void remove(T listenerToRemove) {
|
||||
for (int i = listeners.size()-1; i >= 0; --i) {
|
||||
T listener = listeners.get(i).get();
|
||||
if (listener == null || listener == listenerToRemove) {
|
||||
listeners.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void callAllListeners(Function<T> e) {
|
||||
for (int i = listeners.size()-1; i >= 0; --i) {
|
||||
T listener = listeners.get(i).get();
|
||||
if (listener == null) listeners.remove(i);
|
||||
else e.call(listener);
|
||||
}
|
||||
}
|
||||
protected <Arg1> void callAllListeners(Function1<T, Arg1> e, Arg1 arg) {
|
||||
for (int i = listeners.size()-1; i >= 0; --i) {
|
||||
T listener = listeners.get(i).get();
|
||||
if (listener == null) listeners.remove(i);
|
||||
else e.call(listener, arg);
|
||||
}
|
||||
}
|
||||
protected <Arg1, Arg2> void callAllListeners(Function2<T, Arg1, Arg2> e, Arg1 arg1, Arg2 arg2) {
|
||||
for (int i = listeners.size()-1; i >= 0; --i) {
|
||||
T listener = listeners.get(i).get();
|
||||
if (listener == null) listeners.remove(i);
|
||||
else e.call(listener, arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
protected static interface Function<Listener> {
|
||||
public void call(Listener listener);
|
||||
}
|
||||
protected static interface Function1<Listener, Arg1> {
|
||||
public void call(Listener listener, Arg1 arg1);
|
||||
}
|
||||
protected static interface Function2<Listener, Arg1, Arg2> {
|
||||
public void call(Listener listener, Arg1 arg1, Arg2 arg2);
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,15 @@ import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.Animation.AnimationListener;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences;
|
||||
import com.gpl.rpg.AndorsTrail.Dialogs;
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
import com.gpl.rpg.AndorsTrail.R;
|
||||
@@ -33,15 +37,20 @@ public final class CombatView extends RelativeLayout {
|
||||
private final WorldContext world;
|
||||
private final ViewContext view;
|
||||
private final Resources res;
|
||||
private final AndorsTrailPreferences preferences;
|
||||
private final Player player;
|
||||
private final Animation displayAnimation;
|
||||
private final Animation hideAnimation;
|
||||
|
||||
private Monster currentMonster;
|
||||
|
||||
public CombatView(final Context context, AttributeSet attr) {
|
||||
super(context, attr);
|
||||
AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivityContext(context);
|
||||
this.world = app.world;
|
||||
this.player = world.model.player;
|
||||
this.view = app.currentView.get();
|
||||
this.preferences = app.preferences;
|
||||
this.res = getResources();
|
||||
|
||||
setFocusable(false);
|
||||
@@ -90,6 +99,16 @@ public final class CombatView extends RelativeLayout {
|
||||
|
||||
monsterBar.setBackgroundColor(res.getColor(color.transparent));
|
||||
actionBar.setBackgroundColor(res.getColor(color.transparent));
|
||||
|
||||
displayAnimation = AnimationUtils.loadAnimation(context, R.anim.showcombatbar);
|
||||
hideAnimation = AnimationUtils.loadAnimation(context, R.anim.hidecombatbar);
|
||||
hideAnimation.setAnimationListener(new AnimationListener() {
|
||||
@Override public void onAnimationStart(Animation animation) {}
|
||||
@Override public void onAnimationRepeat(Animation animation) {}
|
||||
@Override public void onAnimationEnd(Animation arg0) {
|
||||
CombatView.this.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void updateTurnInfo(Monster currentActiveMonster) {
|
||||
@@ -135,4 +154,20 @@ public final class CombatView extends RelativeLayout {
|
||||
}
|
||||
updateCombatSelection(world.model.uiSelections.selectedMonster, world.model.uiSelections.selectedPosition);
|
||||
}
|
||||
|
||||
public void show() {
|
||||
setVisibility(View.VISIBLE);
|
||||
bringToFront();
|
||||
if (preferences.enableUiAnimations) {
|
||||
startAnimation(displayAnimation);
|
||||
}
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
if (preferences.enableUiAnimations) {
|
||||
startAnimation(hideAnimation);
|
||||
} else {
|
||||
setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
package com.gpl.rpg.AndorsTrail.view;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.Animation.AnimationListener;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.RelativeLayout.LayoutParams;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences;
|
||||
import com.gpl.rpg.AndorsTrail.R;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Actor;
|
||||
import com.gpl.rpg.AndorsTrail.model.listeners.ActorConditionListener;
|
||||
import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
|
||||
|
||||
public class DisplayActiveActorConditionIcons implements ActorConditionListener {
|
||||
|
||||
private final AndorsTrailPreferences preferences;
|
||||
private final TileManager tileManager;
|
||||
private final RelativeLayout activeConditions;
|
||||
private final ArrayList<ActiveConditionIcon> currentConditionIcons = new ArrayList<ActiveConditionIcon>();
|
||||
private final WeakReference<Context> androidContext;
|
||||
|
||||
public DisplayActiveActorConditionIcons(
|
||||
final AndorsTrailPreferences preferences,
|
||||
final TileManager tileManager,
|
||||
Context androidContext,
|
||||
RelativeLayout activeConditions) {
|
||||
this.preferences = preferences;
|
||||
this.tileManager = tileManager;
|
||||
this.androidContext = new WeakReference<Context>(androidContext);
|
||||
this.activeConditions = activeConditions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActorConditionAdded(Actor actor, ActorCondition condition) {
|
||||
ActiveConditionIcon icon = getFirstFreeIcon();
|
||||
icon.setActiveCondition(condition);
|
||||
icon.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActorConditionRemoved(Actor actor, ActorCondition condition) {
|
||||
ActiveConditionIcon icon = getIconFor(condition);
|
||||
if (icon == null) return;
|
||||
icon.hide(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActorConditionDurationChanged(Actor actor, ActorCondition condition) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActorConditionMagnitudeChanged(Actor actor, ActorCondition condition) {
|
||||
ActiveConditionIcon icon = getIconFor(condition);
|
||||
if (icon == null) return;
|
||||
icon.setIconText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActorConditionRoundEffectApplied(Actor actor, ActorCondition condition) {
|
||||
ActiveConditionIcon icon = getIconFor(condition);
|
||||
if (icon == null) return;
|
||||
icon.pulseAnimate();
|
||||
}
|
||||
|
||||
public void unsubscribe(final WorldContext world) {
|
||||
world.model.player.conditionListener.remove(this);
|
||||
for (ActiveConditionIcon icon : currentConditionIcons) icon.condition = null;
|
||||
}
|
||||
|
||||
public void subscribe(final WorldContext world) {
|
||||
for (ActiveConditionIcon icon : currentConditionIcons) icon.hide(false);
|
||||
for (ActorCondition condition : world.model.player.conditions) {
|
||||
getFirstFreeIcon().setActiveCondition(condition);
|
||||
}
|
||||
world.model.player.conditionListener.add(this);
|
||||
}
|
||||
|
||||
private final class ActiveConditionIcon implements AnimationListener {
|
||||
public final int id;
|
||||
public ActorCondition condition;
|
||||
public final ImageView image;
|
||||
public final TextView text;
|
||||
private final Animation onNewIconAnimation;
|
||||
private final Animation onRemovedIconAnimation;
|
||||
private final Animation onAppliedEffectAnimation;
|
||||
|
||||
public ActiveConditionIcon(Context context, int id) {
|
||||
this.id = id;
|
||||
this.image = new ImageView(context);
|
||||
this.image.setId(id);
|
||||
this.text = new TextView(context);
|
||||
this.onNewIconAnimation = AnimationUtils.loadAnimation(context, R.anim.scaleup);
|
||||
this.onRemovedIconAnimation = AnimationUtils.loadAnimation(context, R.anim.scaledown);
|
||||
this.onAppliedEffectAnimation = AnimationUtils.loadAnimation(context, R.anim.scalebeat);
|
||||
this.onRemovedIconAnimation.setAnimationListener(this);
|
||||
|
||||
final Resources res = context.getResources();
|
||||
|
||||
text.setTextColor(res.getColor(android.R.color.white));
|
||||
text.setShadowLayer(1, 1, 1, res.getColor(android.R.color.black));
|
||||
}
|
||||
|
||||
private void setActiveCondition(ActorCondition condition) {
|
||||
this.condition = condition;
|
||||
tileManager.setImageViewTile(image, condition.conditionType);
|
||||
image.setVisibility(View.VISIBLE);
|
||||
setIconText();
|
||||
}
|
||||
|
||||
public void setIconText() {
|
||||
boolean showMagnitude = (condition.magnitude != 1);
|
||||
if (showMagnitude) {
|
||||
text.setText(Integer.toString(condition.magnitude));
|
||||
text.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
text.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public void hide(boolean useAnimation) {
|
||||
if (useAnimation) {
|
||||
if (preferences.enableUiAnimations) {
|
||||
image.startAnimation(onRemovedIconAnimation);
|
||||
} else {
|
||||
onAnimationEnd(onRemovedIconAnimation);
|
||||
}
|
||||
} else {
|
||||
image.setVisibility(View.GONE);
|
||||
condition = null;
|
||||
}
|
||||
text.setVisibility(View.GONE);
|
||||
}
|
||||
public void show() {
|
||||
if (!preferences.enableUiAnimations) return;
|
||||
image.startAnimation(onNewIconAnimation);
|
||||
if (text.getVisibility() == View.VISIBLE) text.startAnimation(onNewIconAnimation);
|
||||
}
|
||||
|
||||
public void pulseAnimate() {
|
||||
if (!preferences.enableUiAnimations) return;
|
||||
image.startAnimation(onAppliedEffectAnimation);
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return condition != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
if (animation == this.onRemovedIconAnimation) {
|
||||
hide(false);
|
||||
rearrangeIconsLeftOf(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onAnimationRepeat(Animation animation) { }
|
||||
@Override public void onAnimationStart(Animation animation) { }
|
||||
}
|
||||
|
||||
protected void rearrangeIconsLeftOf(ActiveConditionIcon icon) {
|
||||
int i = currentConditionIcons.indexOf(icon);
|
||||
currentConditionIcons.remove(i);
|
||||
currentConditionIcons.add(icon);
|
||||
for(; i < currentConditionIcons.size(); ++i) {
|
||||
currentConditionIcons.get(i).image.setLayoutParams(getLayoutParamsForIconIndex(i));
|
||||
}
|
||||
}
|
||||
|
||||
private ActiveConditionIcon getIconFor(ActorCondition condition) {
|
||||
for (ActiveConditionIcon icon : currentConditionIcons) {
|
||||
if (icon.condition == condition) return icon;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private ActiveConditionIcon getFirstFreeIcon() {
|
||||
for (ActiveConditionIcon icon : currentConditionIcons) {
|
||||
if (!icon.isVisible()) return icon;
|
||||
}
|
||||
return addNewActiveConditionIcon();
|
||||
}
|
||||
|
||||
private RelativeLayout.LayoutParams getLayoutParamsForIconIndex(int index) {
|
||||
RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
layout.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
|
||||
if (index == 0) {
|
||||
layout.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
|
||||
} else {
|
||||
layout.addRule(RelativeLayout.LEFT_OF, currentConditionIcons.get(index-1).id);
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
private ActiveConditionIcon addNewActiveConditionIcon() {
|
||||
int index = currentConditionIcons.size();
|
||||
|
||||
ActiveConditionIcon icon = new ActiveConditionIcon(androidContext.get(), index+1);
|
||||
|
||||
activeConditions.addView(icon.image, getLayoutParamsForIconIndex(index));
|
||||
|
||||
RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
layout.addRule(RelativeLayout.ALIGN_RIGHT, icon.id);
|
||||
layout.addRule(RelativeLayout.ALIGN_BOTTOM, icon.id);
|
||||
activeConditions.addView(icon.text, layout);
|
||||
|
||||
currentConditionIcons.add(icon);
|
||||
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import com.gpl.rpg.AndorsTrail.activity.MainActivity;
|
||||
import com.gpl.rpg.AndorsTrail.activity.HeroinfoActivity;
|
||||
import com.gpl.rpg.AndorsTrail.context.ViewContext;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
|
||||
import com.gpl.rpg.AndorsTrail.model.actor.Player;
|
||||
import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
|
||||
|
||||
@@ -17,8 +16,6 @@ import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.ImageButton;
|
||||
|
||||
@@ -97,15 +94,6 @@ public final class StatusView extends RelativeLayout {
|
||||
world.tileManager.setImageViewTile(heroImage, player);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateActiveConditions(Context androidContext, LinearLayout activeConditions) {
|
||||
GreedyImageViewAppender t = new GreedyImageViewAppender(androidContext, activeConditions);
|
||||
for (ActorCondition condition : player.conditions) {
|
||||
ImageView iv = t.getNextImage();
|
||||
world.tileManager.setImageViewTile(iv, condition.conditionType);
|
||||
}
|
||||
t.removeOtherImages();
|
||||
}
|
||||
|
||||
public void updateQuickItemImage(boolean visible){
|
||||
if(visible){
|
||||
@@ -114,41 +102,4 @@ public final class StatusView extends RelativeLayout {
|
||||
world.tileManager.setImageViewTileForUIIcon(quickToggle, TileManager.iconID_boxclosed);
|
||||
}
|
||||
}
|
||||
|
||||
private static class GreedyImageViewAppender {
|
||||
private final LinearLayout container;
|
||||
private final Context context;
|
||||
private int currentChildIndex = 0;
|
||||
private final int previousChildCount;
|
||||
private final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
|
||||
public GreedyImageViewAppender(Context context, LinearLayout container) {
|
||||
this.container = container;
|
||||
this.context = context;
|
||||
this.previousChildCount = container.getChildCount();
|
||||
}
|
||||
public ImageView getNextImage() {
|
||||
// Since this is called a lot, we do not want to recreate the view objects every time.
|
||||
// Therefore, we reuse existing ImageView:s if they are present, but just change the image on them.
|
||||
ImageView iv;
|
||||
if (currentChildIndex < previousChildCount) {
|
||||
// There already is a create dimage on this position, reuse it.
|
||||
iv = (ImageView) container.getChildAt(currentChildIndex);
|
||||
iv.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
// The player has never had this many conditions, create a new ImageView to hold the condition image.
|
||||
iv = new ImageView(context);
|
||||
container.addView(iv, layoutParams);
|
||||
}
|
||||
++currentChildIndex;
|
||||
return iv;
|
||||
}
|
||||
public void removeOtherImages() {
|
||||
for(int i = previousChildCount - 1; i >= currentChildIndex; --i) {
|
||||
//container.removeViewAt(i);
|
||||
// Don't actually remove them, just hide them (so we won't have to recreate them next time the player get a condition)
|
||||
container.getChildAt(i).setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user