Merge remote-tracking branch 'origin/animated_moves' into tbrawl_attack_missed_animation

This commit is contained in:
Zukero
2015-04-14 10:32:30 +02:00
21 changed files with 310 additions and 46 deletions

View File

@@ -62,7 +62,7 @@
"monsterClass": "insect",
"maxHP": 10,
"maxAP": 10,
"moveCost": 10,
"moveCost": 5,
"attackCost": 10,
"attackChance": 50,
"droplistID": "debuglist1",

View File

@@ -16,6 +16,8 @@
Additional programming by Ethan Wessel<br />
Additional programming by Scott Lund<br />
Additional programming by <a href="https://github.com/Zukero">Kevin Pochat</a><br />
Additional programming by Lucas Delvallet<br />
Additional programming by Florian Doublet<br />
Additional graphics by Karvis<br />
Russian translation by Dreamer..., e.solodookhin, shell.andor, konstmih, istasman, Aleksey Kabanov, Alexander Zubok, Paul Sulemenkov and dromoz<br />
Italian translation by k6blue, liogiu, Joker and Andrea Luciano Damico<br />

View File

@@ -355,8 +355,11 @@
<item>@xml/blackwater_mountain3</item>
<item>@xml/blackwater_mountain4</item>
<item>@xml/blackwater_mountain5</item>
<item>@xml/blackwater_mountain5a</item>
<item>@xml/blackwater_mountain5c</item>
<item>@xml/blackwater_mountain6</item>
<item>@xml/blackwater_mountain7</item>
<item>@xml/blackwater_mountain7a</item>
<item>@xml/blackwater_mountain8</item>
<item>@xml/blackwater_mountain9</item>
<item>@xml/blackwater_mountain10</item>

View File

@@ -174,11 +174,11 @@
<property name="place" value="north"/>
</properties>
</object>
<object name="quest:queststage" type="replace" x="192" y="352" width="96" height="128">
<object name="futurequest:10" type="replace" x="192" y="352" width="96" height="128">
<properties>
<property name="Above" value="Above_replace"/>
<property name="Objects" value="Objects_replace"/>
<property name="Walkalbe" value="Walkalbe_replace"/>
<property name="Walkable" value="Walkable_replace"/>
</properties>
</object>
</objectgroup>

View File

@@ -237,15 +237,10 @@
</objectgroup>
<objectgroup name="Keys" width="19" height="12"/>
<objectgroup name="Replace" width="19" height="12">
<object name="quest:queststage" type="replace" x="0" y="224" width="192" height="96">
<object name="futurequest:10" type="replace" x="0" y="192" width="192" height="128">
<properties>
<property name="Walkalbe" value="Walkalbe_replace"/>
</properties>
</object>
<object name="quest:queststage" type="replace" x="0" y="192" width="192" height="128">
<properties>
<property name="Above" value="Walkable_replace"/>
<property name="Objects" value="Objects_replace"/>
<property name="Walkable" value="Walkable_replace"/>
</properties>
</object>
</objectgroup>

View File

@@ -122,12 +122,12 @@
</tileset>
<layer name="Ground" width="10" height="10">
<data encoding="base64" compression="zlib">
eJw7ysbAcHSQ4ydUNOsEEqalultkmgcAw35PpQ==
eJw7ysbAcHQQ4wYOBoYnVDTvBBKmpbpbZJoHAISsT2I=
</data>
</layer>
<layer name="Objects" width="10" height="10">
<data encoding="base64" compression="zlib">
eJxjYMAOktlxSNAYSFDRXlsm6plFLwAA6HwAyQ==
eJyby88AB7FI7JvMDBSDbDLMyOQnrIZYYMtEPbNIBfPI9AcAQ5QDxw==
</data>
</layer>
<layer name="Above" width="10" height="10">
@@ -140,7 +140,7 @@
eJxjYBi+wFVgoF1AOgAAPUQAVg==
</data>
</layer>
<objectgroup name="Object Layer 1">
<objectgroup name="Object Layer 1" width="0" height="0">
<object name="debugsign" type="sign" x="192" y="96" width="32" height="32"/>
<object name="start" type="rest" x="96" y="64" width="32" height="32"/>
<object name="Unopenable key area" type="key" x="32" y="128" width="32" height="32">
@@ -181,10 +181,10 @@
</properties>
</object>
</objectgroup>
<objectgroup name="Spawn">
<objectgroup name="Spawn" width="0" height="0">
<object name="insect" type="spawn" x="96" y="128" width="192" height="160">
<properties>
<property name="quantity" value="2"/>
<property name="quantity" value="15"/>
</properties>
</object>
<object name="troll" type="spawn" x="256" y="256" width="64" height="64">

View File

@@ -35,6 +35,7 @@ import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
import java.util.ArrayList;
import java.util.ListIterator;
public final class ConversationActivity
extends Activity
@@ -46,11 +47,16 @@ public final class ConversationActivity
private static final int playerPhraseColor = 0;
private static final int NPCPhraseColor = 0;
private static final int rewardColor = Color.argb(255, 0x99, 0x99, 0x55);
private static final int oldPhraseColor = Color.argb(255,0x5a,0x5a, 0x5a);
private static final int oldPlayerNameColor = Color.argb(255, 0x5d, 0x11, 0x11);
private static final int oldNPCNameColor = Color.argb(255, 0x5d, 0x5d, 0x11);
private static final int oldRewardColor = Color.argb(255, 0x4C, 0x4C, 0x2A);
private WorldContext world;
private Player player;
private final ArrayList<ConversationStatement> conversationHistory = new ArrayList<ConversationStatement>();
private ConversationController.ConversationStatemachine conversationState;
private int numberOfNewMessage = 0;
private StatementContainerAdapter listAdapter;
private Button nextButton;
@@ -206,7 +212,26 @@ public final class ConversationActivity
return null; // No reply was found. This is probably an error.
}
private void greyAllConversationStatement(){
int numberOfMessage = this.conversationHistory.size();
while(numberOfNewMessage != 0){
ConversationStatement conversation = conversationHistory.get(numberOfMessage - numberOfNewMessage);
if(conversation.hasActor()){
conversation.textColor = oldPhraseColor;
if(conversation.isPlayerActor){
conversation.nameColor = oldPlayerNameColor;
} else {
conversation.nameColor = oldNPCNameColor;
}
}else{
conversation.textColor = oldRewardColor;
}
numberOfNewMessage--;
}
}
private void nextButtonClicked() {
greyAllConversationStatement();
RadioButton rb = getSelectedReplyButton();
replyGroup.removeAllViews();
nextButton.setEnabled(false);
@@ -233,6 +258,7 @@ public final class ConversationActivity
s.textColor = textColor;
s.isPlayerActor = actor != null && actor == player;
conversationHistory.add(s);
numberOfNewMessage++;
statementList.clearFocus();
listAdapter.notifyDataSetChanged();
statementList.requestLayout();

View File

@@ -13,7 +13,6 @@ import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
@SuppressWarnings("unused")
public final class DebugInterface {
private final ControllerContext controllerContext;
private final MainActivity mainActivity;

View File

@@ -32,7 +32,7 @@ public final class Constants {
public static final int TICKS_PER_FULLROUND = FULLROUND_DURATION / TICK_DELAY;
public static final int SPLATTER_DURATION_MS = 20000;
public static final ConstRange monsterWaitTurns = new ConstRange(30,4);
public static final ConstRange monsterWaitTurns = new ConstRange(5,1);
public static final long MAP_UNVISITED_RESPAWN_DURATION_MS = 3 * 60 * 1000; // 3 min in milliseconds
public static final String PREFERENCE_MODEL_LASTRUNVERSION = "lastversion";

View File

@@ -1,11 +1,18 @@
package com.gpl.rpg.AndorsTrail.controller;
import java.util.ArrayList;
import android.content.res.Resources;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.model.GameStatistics;
import com.gpl.rpg.AndorsTrail.model.ability.*;
import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionEffect;
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionType;
import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection;
import com.gpl.rpg.AndorsTrail.model.ability.SkillInfo;
import com.gpl.rpg.AndorsTrail.model.actor.Actor;
import com.gpl.rpg.AndorsTrail.model.actor.Monster;
import com.gpl.rpg.AndorsTrail.model.actor.Player;
@@ -25,8 +32,6 @@ import com.gpl.rpg.AndorsTrail.model.script.ScriptEffect;
import com.gpl.rpg.AndorsTrail.util.ConstRange;
import com.gpl.rpg.AndorsTrail.util.L;
import java.util.ArrayList;
public final class ConversationController {
private final ControllerContext controllers;
@@ -108,6 +113,9 @@ public final class ConversationController {
case deactivateMapChangeArea:
deactivateMapChangeArea(effect.mapName, effect.effectID);
break;
case removeQuestProgress:
addRemoveQuestProgressReward(player, effect.effectID, effect.value);
break;
}
}
@@ -156,14 +164,21 @@ public final class ConversationController {
private void addQuestProgressReward(Player player, String questID, int questProgress, ScriptEffectResult result) {
QuestProgress progress = new QuestProgress(questID, questProgress);
boolean added = player.addQuestProgress(progress);
if (!added) return; // Only apply exp reward if the quest stage was reached just now (and not re-reached)
QuestLogEntry stage = world.quests.getQuestLogEntry(progress);
if (stage == null) return;
result.loot.exp += stage.rewardExperience;
result.questProgress.add(progress);
}
private void addRemoveQuestProgressReward(Player player, String questID, int questProgress) {
QuestProgress progress = new QuestProgress(questID, questProgress);
player.removeQuestProgress(progress);
}
private void addDropListReward(Player player, String droplistID, ScriptEffectResult result) {
world.dropLists.getDropList(droplistID).createRandomLoot(result.loot, player);
}

View File

@@ -74,7 +74,7 @@ public final class MonsterMovementController implements EvaluateWalkable {
private void moveMonster(final Monster m, final MonsterSpawnArea area) {
PredefinedMap map = world.model.currentMap;
LayeredTileMap tileMap = world.model.currentTileMap;
m.nextActionTime += getMillisecondsPerMove(m);
m.nextActionTime = System.currentTimeMillis() + getMillisecondsPerMove(m);
if (m.movementDestination == null) {
// Monster has waited and should start to move again.
m.movementDestination = new Coord(m.position);
@@ -128,7 +128,7 @@ public final class MonsterMovementController implements EvaluateWalkable {
private static void cancelCurrentMonsterMovement(final Monster m) {
m.movementDestination = null;
m.nextActionTime += getMillisecondsPerMove(m) * Constants.rollValue(Constants.monsterWaitTurns);
m.nextActionTime = System.currentTimeMillis() + (getMillisecondsPerMove(m) * Constants.rollValue(Constants.monsterWaitTurns));
}
private static int getMillisecondsPerMove(Monster m) {
@@ -151,9 +151,17 @@ public final class MonsterMovementController implements EvaluateWalkable {
return monsterCanMoveTo(world.model.currentMap, world.model.currentTileMap, r);
}
public void moveMonsterToNextPosition(Monster m, PredefinedMap map) {
CoordRect previousPosition = new CoordRect(new Coord(m.position), m.rectPosition.size);
public void moveMonsterToNextPosition(final Monster m, final PredefinedMap map) {
final CoordRect previousPosition = new CoordRect(new Coord(m.position), m.rectPosition.size);
m.lastPosition.set(previousPosition.topLeft);
m.position.set(m.nextPosition.topLeft);
monsterMovementListeners.onMonsterMoved(map, m, previousPosition);
controllers.effectController.startActorMoveEffect(m, previousPosition.topLeft, m.position, getMillisecondsPerMove(m) / 4, new VisualEffectController.VisualEffectCompletedCallback() {
@Override
public void onVisualEffectCompleted(int callbackValue) {
monsterMovementListeners.onMonsterMoved(map, m, previousPosition);
}
}, 0);
}
}

View File

@@ -228,15 +228,24 @@ public final class MovementController implements TimedMessageTask.Callback {
player.lastPosition.set(player.position);
player.position.set(newPosition);
controllers.combatController.setCombatSelection(null, null);
playerMovementListeners.onPlayerMoved(newPosition, player.lastPosition);
controllers.effectController.startActorMoveEffect(player, player.lastPosition, newPosition, (int) (Constants.MINIMUM_INPUT_INTERVAL / 2), new VisualEffectController.VisualEffectCompletedCallback() {
@Override
public void onVisualEffectCompleted(int callbackValue) {
playerMovementListeners.onPlayerMoved(newPosition, player.lastPosition);
controllers.mapController.handleMapEventsAfterMovement(currentMap, newPosition, player.lastPosition);
controllers.mapController.handleMapEventsAfterMovement(currentMap, newPosition, player.lastPosition);
if (!world.model.uiSelections.isInCombat) {
//currentMap can be outdated due to mapchange events processed above.
Loot loot = world.model.currentMap.getBagAt(newPosition);
if (loot != null) controllers.itemController.playerSteppedOnLootBag(loot);
}
if (!world.model.uiSelections.isInCombat) {
//currentMap can be outdated due to mapchange events processed above.
Loot loot = world.model.currentMap.getBagAt(newPosition);
if (loot != null) controllers.itemController.playerSteppedOnLootBag(loot);
}
}
}, 0);
}
public void respawnPlayer(Resources res) {

View File

@@ -4,9 +4,11 @@ import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.os.Handler;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.listeners.VisualEffectFrameListeners;
import com.gpl.rpg.AndorsTrail.model.actor.Actor;
import com.gpl.rpg.AndorsTrail.model.actor.Monster;
import com.gpl.rpg.AndorsTrail.model.actor.MonsterType;
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
@@ -54,7 +56,70 @@ public final class VisualEffectController {
enqueuedEffectID = null;
enqueuedEffectValue = 0;
}
public void startActorMoveEffect(Actor actor, Coord origin, Coord destination, int duration, VisualEffectCompletedCallback callback, int callbackValue) {
++effectCount;
(new SpriteMoveAnimation(origin, destination, duration, actor, callback, callbackValue))
.start();
}
public final class SpriteMoveAnimation extends Handler implements Runnable {
private static final int millisecondsPerFrame=25;
private final VisualEffectCompletedCallback callback;
private final int callbackValue;
public final int duration;
public final Actor actor;
public final Coord origin;
public final Coord destination;
public int timeElapsed;
@Override
public void run() {
update();
if (System.currentTimeMillis() - actor.vfxStartTime >= duration) {
onCompleted();
} else {
postDelayed(this, millisecondsPerFrame);
}
}
public SpriteMoveAnimation(Coord origin, Coord destination, int duration, Actor actor, VisualEffectCompletedCallback callback, int callbackValue) {
this.callback = callback;
this.callbackValue = callbackValue;
this.duration = duration;
this.actor = actor;
this.origin = origin;
this.destination = destination;
this.timeElapsed = 0;
}
private void update() {
visualEffectFrameListeners.onNewSpriteMoveFrame(this);
}
private void onCompleted() {
--effectCount;
actor.hasVFXRunning = false;
if (callback != null) callback.onVisualEffectCompleted(callbackValue);
visualEffectFrameListeners.onSpriteMoveCompleted(this);
}
public void start() {
actor.hasVFXRunning = true;
actor.vfxDuration = duration;
actor.vfxStartTime = System.currentTimeMillis();
postDelayed(this, 0);
}
}
public final class VisualEffectAnimation extends Handler implements Runnable {
@Override

View File

@@ -1,8 +1,11 @@
package com.gpl.rpg.AndorsTrail.controller.listeners;
import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.SpriteMoveAnimation;
import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.VisualEffectAnimation;
public interface VisualEffectFrameListener {
void onNewAnimationFrame(VisualEffectAnimation animation, int tileID, int textYOffset);
void onAnimationCompleted(VisualEffectAnimation animation);
void onNewSpriteMoveFrame(SpriteMoveAnimation animation);
void onSpriteMoveCompleted(SpriteMoveAnimation animation);
}

View File

@@ -1,5 +1,6 @@
package com.gpl.rpg.AndorsTrail.controller.listeners;
import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.SpriteMoveAnimation;
import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.VisualEffectAnimation;
import com.gpl.rpg.AndorsTrail.util.ListOfListeners;
@@ -12,6 +13,14 @@ public final class VisualEffectFrameListeners extends ListOfListeners<VisualEffe
private final Function1<VisualEffectFrameListener, VisualEffectAnimation> onAnimationCompleted = new Function1<VisualEffectFrameListener, VisualEffectAnimation>() {
@Override public void call(VisualEffectFrameListener listener, VisualEffectAnimation animation) { listener.onAnimationCompleted(animation); }
};
private final Function1<VisualEffectFrameListener, SpriteMoveAnimation> onNewSpriteMoveFrame = new Function1<VisualEffectFrameListener, SpriteMoveAnimation>() {
@Override public void call(VisualEffectFrameListener listener, SpriteMoveAnimation animation) { listener.onNewSpriteMoveFrame(animation); }
};
private final Function1<VisualEffectFrameListener, SpriteMoveAnimation> onSpriteMoveCompleted = new Function1<VisualEffectFrameListener, SpriteMoveAnimation>() {
@Override public void call(VisualEffectFrameListener listener, SpriteMoveAnimation animation) { listener.onSpriteMoveCompleted(animation); }
};
@Override
public void onNewAnimationFrame(VisualEffectAnimation animation, int tileID, int textYOffset) {
@@ -22,4 +31,14 @@ public final class VisualEffectFrameListeners extends ListOfListeners<VisualEffe
public void onAnimationCompleted(VisualEffectAnimation animation) {
callAllListeners(this.onAnimationCompleted, animation);
}
@Override
public void onNewSpriteMoveFrame(SpriteMoveAnimation animation) {
callAllListeners(this.onNewSpriteMoveFrame, animation);
}
@Override
public void onSpriteMoveCompleted(SpriteMoveAnimation animation) {
callAllListeners(this.onSpriteMoveCompleted, animation);
}
}

View File

@@ -34,6 +34,10 @@ public class Actor {
public int blockChance;
public int damageResistance;
public ItemTraits_OnUse[] onHitEffects;
public boolean hasVFXRunning = false;
public long vfxStartTime = 0;
public int vfxDuration = 0;
public final Coord lastPosition = new Coord();
public Actor(
Size tileSize

View File

@@ -1,7 +1,15 @@
package com.gpl.rpg.AndorsTrail.model.actor;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import android.util.FloatMath;
import android.util.SparseIntArray;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
@@ -18,17 +26,9 @@ import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.Range;
import com.gpl.rpg.AndorsTrail.util.Size;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
public final class Player extends Actor {
public static final int DEFAULT_PLAYER_ATTACKCOST = 4;
public final Coord lastPosition;
public final Coord nextPosition;
// TODO: Should be privates
@@ -86,7 +86,6 @@ public final class Player extends Actor {
, true // isPlayer
, false // isImmuneToCriticalHits
);
this.lastPosition = new Coord();
this.nextPosition = new Coord();
this.levelExperience = new Range();
this.inventory = new Inventory();
@@ -154,6 +153,12 @@ public final class Player extends Actor {
return true; //Progress was added.
}
public boolean removeQuestProgress(QuestProgress progress){
if (!hasExactQuestProgress(progress.questID, progress.progress)) return false;
questProgress.get(progress.questID).remove(progress.progress);
return true; //Progress was removed.
}
public void recalculateLevelExperience() {
int experienceRequiredToReachThisLevel = getRequiredExperience(level);
levelExperience.set(getRequiredExperienceForNextLevel(level), totalExperience - experienceRequiredToReachThisLevel);

View File

@@ -14,6 +14,7 @@ public final class ScriptEffect {
, deactivateSpawnArea
, activateMapChangeArea
, deactivateMapChangeArea
, removeQuestProgress
}
public final ScriptEffectType type;

View File

@@ -72,4 +72,24 @@ public final class CoordRect {
public String toString() {
return '{' + topLeft.toString() + ", " + size.toString() + '}';
}
public static CoordRect getBoundingRect(Coord c1, Coord c2) {
int x, y, w, h;
if (c2.x < c1.x) {
x = c2.x;
w = 1 + c1.x - c2.x;
} else {
x = c1.x;
w = 1 + c2.x - c1.x;
}
if (c2.y < c1.y) {
y = c2.y;
h = 1 + c1.y - c2.y;
} else {
y = c1.y;
h = 1 + c2.y - c1.y;
}
return new CoordRect(new Coord(x, y), new Size(w, h));
}
}

View File

@@ -10,12 +10,14 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences;
import com.gpl.rpg.AndorsTrail.context.ControllerContext;
import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.controller.InputController;
import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.BloodSplatter;
import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.SpriteMoveAnimation;
import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.VisualEffectAnimation;
import com.gpl.rpg.AndorsTrail.controller.listeners.*;
import com.gpl.rpg.AndorsTrail.model.ModelContainer;
@@ -29,6 +31,7 @@ import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection;
import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager;
import com.gpl.rpg.AndorsTrail.util.Coord;
import com.gpl.rpg.AndorsTrail.util.CoordRect;
import com.gpl.rpg.AndorsTrail.util.L;
import com.gpl.rpg.AndorsTrail.util.Size;
public final class MainView extends SurfaceView
@@ -49,7 +52,8 @@ public final class MainView extends SurfaceView
private final Coord screenOffset = new Coord(); // pixel offset where the image begins
private final Coord mapTopLeft = new Coord(); // Map coords of visible map
private CoordRect mapViewArea; // Area in mapcoordinates containing the visible map. topleft == this.topleft
private Rect redrawClip = new Rect(); //Area in screen coordinates containing the visible map.
private final ModelContainer model;
private final WorldContext world;
private final ControllerContext controllers;
@@ -199,6 +203,7 @@ public final class MainView extends SurfaceView
}
}
synchronized (holder) { synchronized (tiles) {
c.clipRect(redrawClip);
c.translate(screenOffset.x, screenOffset.y);
c.scale(scale, scale);
doDrawRect(c, area);
@@ -213,6 +218,34 @@ public final class MainView extends SurfaceView
if (c != null) holder.unlockCanvasAndPost(c);
}
}
private void redrawMoveArea_(CoordRect area, final SpriteMoveAnimation effect) {
if (!hasSurface) return;
if (currentMap.isOutside(area)) return;
if (!mapViewArea.intersects(area)) return;
calculateRedrawRect(area);
Canvas c = null;
try {
c = holder.lockCanvas(redrawRect);
// lockCanvas sometimes changes redrawRect, when the double-buffer has not been
// sufficiently filled beforehand. In those cases, we need to redraw the whole scene.
if (area != mapViewArea) {
if (isRedrawRectWholeScreen(redrawRect)) {
area = mapViewArea;
}
}
synchronized (holder) { synchronized (tiles) {
c.clipRect(redrawClip);
c.translate(screenOffset.x, screenOffset.y);
c.scale(scale, scale);
doDrawRect(c, area);
} }
} finally {
if (c != null) holder.unlockCanvasAndPost(c);
}
}
private boolean isRedrawRectWholeScreen(Rect redrawRect) {
if (redrawRect.width() < mapViewArea.size.width * scaledTileSize) return false;
@@ -256,13 +289,25 @@ public final class MainView extends SurfaceView
}
private void doDrawRect(Canvas canvas, CoordRect area) {
doDrawRect_Below(canvas, area);
doDrawRect_Objects(canvas, area);
doDrawRect_Above(canvas, area);
}
private void doDrawRect_Below(Canvas canvas, CoordRect area) {
drawMapLayer(canvas, area, currentTileMap.currentLayout.layerGround);
tryDrawMapLayer(canvas, area, currentTileMap.currentLayout.layerObjects);
for (BloodSplatter splatter : currentMap.splatters) {
drawFromMapPosition(canvas, area, splatter.position, splatter.iconID);
}
}
private void doDrawRect_Objects(Canvas canvas, CoordRect area) {
for (BloodSplatter splatter : currentMap.splatters) {
drawFromMapPosition(canvas, area, splatter.position, splatter.iconID);
}
for (Loot l : currentMap.groundBags) {
if (l.isVisible) {
@@ -270,13 +315,31 @@ public final class MainView extends SurfaceView
}
}
drawFromMapPosition(canvas, area, playerPosition, model.player.iconID);
if (!model.player.hasVFXRunning) {
drawFromMapPosition(canvas, area, playerPosition, model.player.iconID);
} else if (area.contains(playerPosition)) {
int vfxElapsedTime = (int) (System.currentTimeMillis() - model.player.vfxStartTime);
if (vfxElapsedTime > model.player.vfxDuration) vfxElapsedTime = model.player.vfxDuration;
int x = ((model.player.position.x - mapViewArea.topLeft.x) * tileSize * vfxElapsedTime + ((model.player.lastPosition.x - mapViewArea.topLeft.x) * tileSize * (model.player.vfxDuration - vfxElapsedTime))) / model.player.vfxDuration;
int y = ((model.player.position.y - mapViewArea.topLeft.y) * tileSize * vfxElapsedTime + ((model.player.lastPosition.y - mapViewArea.topLeft.y) * tileSize * (model.player.vfxDuration - vfxElapsedTime))) / model.player.vfxDuration;
tiles.drawTile(canvas, model.player.iconID, x, y, mPaint);
}
for (MonsterSpawnArea a : currentMap.spawnAreas) {
for (Monster m : a.monsters) {
drawFromMapPosition(canvas, area, m.rectPosition, m.iconID);
if (!m.hasVFXRunning) {
drawFromMapPosition(canvas, area, m.rectPosition, m.iconID);
} else if (area.intersects(m.rectPosition) || area.contains(m.lastPosition)) {
int vfxElapsedTime = (int) (System.currentTimeMillis() - m.vfxStartTime);
if (vfxElapsedTime > m.vfxDuration) vfxElapsedTime = m.vfxDuration;
int x = ((m.position.x - mapViewArea.topLeft.x) * tileSize * vfxElapsedTime + ((m.lastPosition.x - mapViewArea.topLeft.x) * tileSize * (m.vfxDuration - vfxElapsedTime))) / m.vfxDuration;
int y = ((m.position.y - mapViewArea.topLeft.y) * tileSize * vfxElapsedTime + ((m.lastPosition.y - mapViewArea.topLeft.y) * tileSize * (m.vfxDuration - vfxElapsedTime))) / m.vfxDuration;
tiles.drawTile(canvas, m.iconID, x, y, mPaint);
}
}
}
}
private void doDrawRect_Above(Canvas canvas, CoordRect area) {
tryDrawMapLayer(canvas, area, currentTileMap.currentLayout.layerAbove);
if (model.uiSelections.selectedPosition != null) {
@@ -342,6 +405,7 @@ public final class MainView extends SurfaceView
,Math.min(screenSizeTileCount.height, currentMap.size.height)
);
mapViewArea = new CoordRect(mapTopLeft, visibleNumberOfTiles);
updateClip();
screenOffset.set(
(surfaceSize.width - scaledTileSize * visibleNumberOfTiles.width) / 2
@@ -370,8 +434,13 @@ public final class MainView extends SurfaceView
mapTopLeft.y = Math.max(0, playerPosition.y - mapViewArea.size.height/2);
mapTopLeft.y = Math.min(mapTopLeft.y, currentMap.size.height - mapViewArea.size.height);
}
updateClip();
}
}
private void updateClip() {
worldCoordsToScreenCords(mapViewArea, redrawClip);
}
@Override
public void onPlayerMoved(Coord newPosition, Coord previousPosition) {
@@ -492,6 +561,16 @@ public final class MainView extends SurfaceView
public void onAnimationCompleted(VisualEffectAnimation animation) {
redrawArea(animation.area, RedrawAreaDebugReason.EffectCompleted);
}
@Override
public void onNewSpriteMoveFrame(SpriteMoveAnimation animation) {
redrawMoveArea_(CoordRect.getBoundingRect(animation.origin, animation.destination), animation);
}
@Override
public void onSpriteMoveCompleted(SpriteMoveAnimation animation) {
redrawArea(CoordRect.getBoundingRect(animation.origin, animation.destination), RedrawAreaDebugReason.EffectCompleted);
}
@Override
public void onNewTick() {

View File

@@ -31,6 +31,7 @@
<label for="rewardType">Reward Type:</label>
<select class="field" id="rewardType" ng-model="reward.rewardType">
<option value="questProgress">Quest progress</option>
<option value="removeQuestProgress">Remove Quest progress</option>
<option value="dropList">Droplist</option>
<option value="skillIncrease">Skill increase</option>
<option value="actorCondition">Actor condition</option>
@@ -74,6 +75,16 @@
<input type="text" size="3" id="rewardvalue" class="field at-input-quantity" ng-model="reward.value" />
</div>
</div>
<div ng-show="reward.rewardType=='removeQuestProgress'">
<div class="fieldWithLabel">
<label for="rewardID">Quest ID:</label>
<input type="text" size="30" id="rewardID" class="field at-input-id" ng-model="reward.rewardID" />
</div>
<div class="fieldWithLabel">
<label for="rewardvalue">Stage:</label>
<input type="text" size="3" id="rewardvalue" class="field at-input-quantity" ng-model="reward.value" />
</div>
</div>
<div ng-show="reward.rewardType=='dropList'">
<div class="fieldWithLabel">
<label for="rewardID">Droplist ID:</label>