diff --git a/AndorsTrail/.gitignore b/AndorsTrail/.gitignore index f2701623b..5c01772b1 100644 --- a/AndorsTrail/.gitignore +++ b/AndorsTrail/.gitignore @@ -1,8 +1,8 @@ # Android ignores -gen -bin -assets -target +gen/ +bin/ +assets/ +target/ #IntelliJ .idea/ @@ -15,4 +15,4 @@ local.properties # Other .metadata -.svn +.svn/ diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailApplication.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailApplication.java index 3229c6271..5b7415d9a 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailApplication.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailApplication.java @@ -1,7 +1,5 @@ package com.gpl.rpg.AndorsTrail; -import java.lang.ref.WeakReference; - import com.gpl.rpg.AndorsTrail.context.ViewContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; @@ -23,10 +21,14 @@ public final class AndorsTrailApplication extends Application { public static final int CURRENT_VERSION = DEVELOPMENT_INCOMPATIBLE_SAVEGAMES ? 999 : 34; public static final String CURRENT_VERSION_DISPLAY = "0.7.0dev"; - public final WorldContext world = new WorldContext(); - public final WorldSetup setup = new WorldSetup(world, this); - public WeakReference currentView; - public final AndorsTrailPreferences preferences = new AndorsTrailPreferences(); + private final AndorsTrailPreferences preferences = new AndorsTrailPreferences(); + private final WorldContext world = new WorldContext(); + private final ViewContext view = new ViewContext(this, world); + private final WorldSetup setup = new WorldSetup(world, view, this); + public WorldContext getWorld() { return world; } + public WorldSetup getWorldSetup() { return setup; } + public AndorsTrailPreferences getPreferences() { return preferences; } + public ViewContext getViewContext() { return view; } public static AndorsTrailApplication getApplicationFromActivity(Activity activity) { return ((AndorsTrailApplication) activity.getApplication()); @@ -40,7 +42,7 @@ public final class AndorsTrailApplication extends Application { public boolean isInitialized() { return world.model != null; } - public static void setWindowParameters(Activity activity, final AndorsTrailPreferences preferences) { + public void setWindowParameters(Activity activity) { activity.requestWindowFeature(Window.FEATURE_NO_TITLE); if (preferences.fullscreen) { activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailPreferences.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailPreferences.java index 1daefb291..82f0f5a87 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailPreferences.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailPreferences.java @@ -4,7 +4,7 @@ import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; -public class AndorsTrailPreferences { +public final class AndorsTrailPreferences { public static final int DISPLAYLOOT_DIALOG = 0; public static final int DISPLAYLOOT_TOAST = 1; public static final int DISPLAYLOOT_NONE = 2; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/Dialogs.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/Dialogs.java index 37347f081..1df58d14a 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/Dialogs.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/Dialogs.java @@ -1,7 +1,8 @@ package com.gpl.rpg.AndorsTrail; -import java.util.Arrays; -import java.util.HashSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import android.app.Activity; import android.app.AlertDialog; @@ -19,7 +20,6 @@ import android.widget.ListView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; -import com.gpl.rpg.AndorsTrail.R; import com.gpl.rpg.AndorsTrail.activity.ActorConditionInfoActivity; import com.gpl.rpg.AndorsTrail.activity.BulkSelectionInterface; import com.gpl.rpg.AndorsTrail.activity.ConversationActivity; @@ -33,14 +33,11 @@ import com.gpl.rpg.AndorsTrail.activity.LevelUpActivity; import com.gpl.rpg.AndorsTrail.activity.MonsterEncounterActivity; import com.gpl.rpg.AndorsTrail.activity.MonsterInfoActivity; import com.gpl.rpg.AndorsTrail.activity.Preferences; -import com.gpl.rpg.AndorsTrail.activity.HeroinfoActivity_Quests; import com.gpl.rpg.AndorsTrail.activity.ShopActivity; import com.gpl.rpg.AndorsTrail.activity.SkillInfoActivity; import com.gpl.rpg.AndorsTrail.activity.StartScreenActivity; import com.gpl.rpg.AndorsTrail.context.ViewContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; -import com.gpl.rpg.AndorsTrail.controller.Controller; -import com.gpl.rpg.AndorsTrail.controller.ItemController; import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionType; import com.gpl.rpg.AndorsTrail.model.actor.Monster; import com.gpl.rpg.AndorsTrail.model.item.ItemType; @@ -112,84 +109,89 @@ public final class Dialogs { currentActivity.startActivityForResult(intent, MainActivity.INTENTREQUEST_MONSTERENCOUNTER); } - public static void showMonsterInfo(final Activity currentActivity, final Monster monster) { - Intent intent = new Intent(currentActivity, MonsterInfoActivity.class); + public static void showMonsterInfo(final Context context, final Monster monster) { + Intent intent = new Intent(context, MonsterInfoActivity.class); intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/monsterinfo")); addMonsterIdentifiers(intent, monster); - currentActivity.startActivity(intent); + context.startActivity(intent); } - public static void showMonsterLoot(final MainActivity mainActivity, final ViewContext context, final HashSet lootBags, int totalExpThisFight) { - // The real object of lootBags will get clear():ed by the caller after we have reached this function. - // Therefore, we make a shallow copy of it to remember the Loot objects that should be modified. - HashSet copy = new HashSet(lootBags); - - String msg = mainActivity.getString(R.string.dialog_monsterloot_message); - showLoot(mainActivity, context, copy, totalExpThisFight, R.string.dialog_monsterloot_title, msg, false); - } - - public static void showGroundLoot(final MainActivity mainActivity, final ViewContext context, final Loot loot) { - String msg = ""; - if (!loot.items.isEmpty()) msg = mainActivity.getString(R.string.dialog_groundloot_message); - showLoot(mainActivity, context, Arrays.asList(loot), 0, R.string.dialog_groundloot_title, msg, !loot.isVisible); - } - - private static void showLoot(final MainActivity mainActivity, final ViewContext context, final Iterable lootBags, final int exp, final int title, String msg, boolean isContainer) { - //if (ItemController.updateLootVisibility(context, lootBags)) return; - - final Loot combinedLoot = new Loot(); - for (Loot l : lootBags) { - combinedLoot.add(l); + public static String getGroundLootMessage(final Context ctx, final Loot loot) { + StringBuilder sb = new StringBuilder(60); + if (!loot.items.isEmpty()) { + sb.append(ctx.getString(R.string.dialog_groundloot_message)); } + if (loot.gold > 0) { + sb.append(' '); + sb.append(ctx.getString(R.string.dialog_loot_foundgold, loot.gold)); + } + appendLootMessage(ctx, loot, sb); + return sb.toString(); + } + public static String getMonsterLootMessage(final Context ctx, final Loot combinedLoot, final int exp) { + StringBuilder sb = new StringBuilder(60); + sb.append(ctx.getString(R.string.dialog_monsterloot_message)); if (exp > 0) { - msg += mainActivity.getString(R.string.dialog_monsterloot_gainedexp, exp); + sb.append(' '); + sb.append(ctx.getString(R.string.dialog_monsterloot_gainedexp, exp)); } - if (combinedLoot.gold > 0) { - msg += mainActivity.getString(R.string.dialog_loot_foundgold, combinedLoot.gold); + appendLootMessage(ctx, combinedLoot, sb); + return sb.toString(); + } + private static void appendLootMessage(final Context ctx, final Loot loot, final StringBuilder sb) { + if (loot.gold > 0) { + sb.append(' '); + sb.append(ctx.getString(R.string.dialog_loot_foundgold, loot.gold)); } - - if (!isContainer) { - if (context.preferences.displayLoot != AndorsTrailPreferences.DISPLAYLOOT_DIALOG) { - if (context.preferences.displayLoot == AndorsTrailPreferences.DISPLAYLOOT_TOAST) { - int numItems = combinedLoot.items.countItems(); - if (numItems == 1) { - msg += mainActivity.getString(R.string.dialog_loot_pickedupitem); - } else if (numItems > 1){ - msg += mainActivity.getString(R.string.dialog_loot_pickedupitems, numItems); - } - mainActivity.showToast(msg, Toast.LENGTH_LONG); - } - ItemController.pickupAll(lootBags, context.model); - ItemController.updateLootVisibility(context, lootBags); - context.gameRoundController.resume(); - return; - } + int numItems = loot.items.countItems(); + if (numItems == 1) { + sb.append(' '); + sb.append(ctx.getString(R.string.dialog_loot_pickedupitem)); + } else if (numItems > 1){ + sb.append(' '); + sb.append(ctx.getString(R.string.dialog_loot_pickedupitems, numItems)); } - + } + + public static void showMonsterLoot(final MainActivity mainActivity, final ViewContext view, final WorldContext world, final Collection lootBags, final Loot combinedLoot, final String msg) { + // CombatController will do killedMonsterBags.clear() after this method has been called, + // so we need to keep the list of objects. Therefore, we create a shallow copy of the list of bags. + ArrayList bags = new ArrayList(lootBags); + showLoot(mainActivity, view, world, combinedLoot, bags, R.string.dialog_monsterloot_title, msg); + } + + public static void showGroundLoot(final MainActivity mainActivity, final ViewContext view, final WorldContext world, final Loot loot, final String msg) { + showLoot(mainActivity, view, world, loot, Collections.singletonList(loot), R.string.dialog_monsterloot_title, msg); + } + + private static void showLoot(final MainActivity mainActivity, final ViewContext view, final WorldContext world, final Loot combinedLoot, final Iterable lootBags, final int title, final String msg) { final ListView itemList = new ListView(mainActivity); itemList.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, ListView.LayoutParams.WRAP_CONTENT)); itemList.setPadding(20, 0, 20, 20); itemList.setOnItemClickListener(new OnItemClickListener() { @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { + public void onItemClick(AdapterView parent, View v, int position, long id) { final String itemTypeID = ((ItemContainerAdapter) parent.getAdapter()).getItem(position).itemType.id; - combinedLoot.items.removeItem(itemTypeID); for (Loot l : lootBags) { - if (l.items.removeItem(itemTypeID)) break; + if (l.items.removeItem(itemTypeID)) { + view.itemController.removeLootBagIfEmpty(l); + break; + } } - ItemType type = context.itemTypes.getItemType(itemTypeID); - context.model.player.inventory.addItem(type); + combinedLoot.items.removeItem(itemTypeID); + ItemType type = world.itemTypes.getItemType(itemTypeID); + world.model.player.inventory.addItem(type); ((ItemContainerAdapter) itemList.getAdapter()).notifyDataSetChanged(); } }); - itemList.setAdapter(new ItemContainerAdapter(mainActivity, context.tileManager, combinedLoot.items, context.model.player)); + itemList.setAdapter(new ItemContainerAdapter(mainActivity, world.tileManager, combinedLoot.items, world.model.player)); AlertDialog.Builder db = new AlertDialog.Builder(mainActivity) .setTitle(title) .setMessage(msg) - .setIcon(new BitmapDrawable(context.tileManager.preloadedTiles.getBitmap(TileManager.iconID_groundbag))) + .setIcon(new BitmapDrawable(world.tileManager.preloadedTiles.getBitmap(TileManager.iconID_groundbag))) .setNegativeButton(R.string.dialog_close, null) .setView(itemList); @@ -197,17 +199,17 @@ public final class Dialogs { db.setPositiveButton(R.string.dialog_loot_pickall, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - ItemController.pickupAll(lootBags, context.model); + view.itemController.pickupAll(lootBags); } }); } final Dialog d = db.create(); - showDialogAndPause(d, context, new OnDismissListener() { + showDialogAndPause(d, view, new OnDismissListener() { @Override public void onDismiss(DialogInterface arg0) { - ItemController.updateLootVisibility(context, lootBags); + view.itemController.removeLootBagIfEmpty(lootBags); } }); } @@ -228,18 +230,14 @@ public final class Dialogs { currentActivity.startActivityForResult(intent, MainActivity.INTENTREQUEST_LEVELUP); } - public static void showRest(final Activity currentActivity, final ViewContext viewContext, final MapObject area) { - if (!viewContext.preferences.confirmRest) { - Controller.ui_playerRested(currentActivity, viewContext, area); - return; - } + public static void showConfirmRest(final Activity currentActivity, final ViewContext viewContext, final MapObject area) { Dialog d = new AlertDialog.Builder(currentActivity) .setTitle(R.string.dialog_rest_title) .setMessage(R.string.dialog_rest_confirm_message) .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - Controller.ui_playerRested(currentActivity, viewContext, area); + viewContext.controller.rest(area); } }) .setNegativeButton(android.R.string.no, null) @@ -270,8 +268,8 @@ public final class Dialogs { currentActivity.startActivityForResult(intent, MainActivity.INTENTREQUEST_PREFERENCES); } - public static void showSave(final MainActivity mainActivity, final ViewContext viewContext) { - if (viewContext.model.uiSelections.isInCombat) { + public static void showSave(final MainActivity mainActivity, final ViewContext viewContext, final WorldContext world) { + if (world.model.uiSelections.isInCombat) { mainActivity.showToast(mainActivity.getResources().getString(R.string.menu_save_saving_not_allowed_in_combat), Toast.LENGTH_SHORT); return; } @@ -287,11 +285,6 @@ public final class Dialogs { currentActivity.startActivityForResult(intent, StartScreenActivity.INTENTREQUEST_LOADGAME); } - public static void showQuestLog(final Activity currentActivity) { - Intent intent = new Intent(currentActivity, HeroinfoActivity_Quests.class); - currentActivity.startActivity(intent); - } - public static void showActorConditionInfo(final Context context, ActorConditionType conditionType) { Intent intent = new Intent(context, ActorConditionInfoActivity.class); intent.setData(Uri.parse("content://com.gpl.rpg.AndorsTrail/actorconditioninfo/" + conditionType.conditionTypeID)); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/Savegames.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/Savegames.java deleted file mode 100644 index 6e6ccd1a6..000000000 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/Savegames.java +++ /dev/null @@ -1,211 +0,0 @@ -package com.gpl.rpg.AndorsTrail; - -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import android.content.Context; -import android.os.Environment; - -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.Controller; -import com.gpl.rpg.AndorsTrail.controller.MovementController; -import com.gpl.rpg.AndorsTrail.model.ModelContainer; -import com.gpl.rpg.AndorsTrail.util.L; - -public final class Savegames { - public static final int SLOT_QUICKSAVE = 0; - - public static final int LOAD_RESULT_SUCCESS = 0; - public static final int LOAD_RESULT_UNKNOWN_ERROR = 1; - public static final int LOAD_RESULT_FUTURE_VERSION = 2; - - public static boolean saveWorld(WorldContext world, Context androidContext, int slot, String displayInfo) { - try { - // Create the savegame in a temporary memorystream first to ensure that the savegame can - // be created correctly. We don't want to trash the user's file unneccessarily if there is an error. - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - saveWorld(world, bos, displayInfo); - byte[] savegame = bos.toByteArray(); - bos.close(); - bos = null; - - FileOutputStream fos = getOutputFile(androidContext, slot); - fos.write(savegame); - fos.close(); - return true; - } catch (IOException e) { - L.log("Error saving world: " + e.toString()); - return false; - } - } - public static int loadWorld(WorldContext world, Context androidContext, int slot) { - try { - FileInputStream fos = getInputFile(androidContext, slot); - int result = loadWorld(world, fos); - fos.close(); - return result; - } catch (IOException e) { - if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) { - L.log("Error loading world: " + e.toString()); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - e.printStackTrace(pw); - L.log("Load error: " + sw.toString()); - } - return LOAD_RESULT_UNKNOWN_ERROR; - } - } - - private static FileOutputStream getOutputFile(Context androidContext, int slot) throws IOException { - if (slot == SLOT_QUICKSAVE) { - return androidContext.openFileOutput(Constants.FILENAME_SAVEGAME_QUICKSAVE, Context.MODE_PRIVATE); - } else { - ensureSavegameDirectoryExists(); - return new FileOutputStream(getSlotFile(slot)); - } - } - private static void ensureSavegameDirectoryExists() { - File root = Environment.getExternalStorageDirectory(); - File dir = new File(root, Constants.FILENAME_SAVEGAME_DIRECTORY); - if (!dir.exists()) dir.mkdir(); - } - private static FileInputStream getInputFile(Context androidContext, int slot) throws IOException { - if (slot == SLOT_QUICKSAVE) { - return androidContext.openFileInput(Constants.FILENAME_SAVEGAME_QUICKSAVE); - } else { - return new FileInputStream(getSlotFile(slot)); - } - } - private static File getSlotFile(int slot) { - File root = getSavegameDirectory(); - return new File(root, Constants.FILENAME_SAVEGAME_FILENAME_PREFIX + slot); - } - - private static File getSavegameDirectory() { - File root = Environment.getExternalStorageDirectory(); - return new File(root, Constants.FILENAME_SAVEGAME_DIRECTORY); - } - - 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.getName(), displayInfo); - world.maps.writeToParcel(dest, flags); - world.model.writeToParcel(dest, flags); - dest.close(); - } - - public static int loadWorld(WorldContext world, InputStream inState) throws IOException { - DataInputStream src = new DataInputStream(inState); - final FileHeader header = new FileHeader(src); - if (header.fileversion > AndorsTrailApplication.CURRENT_VERSION) return LOAD_RESULT_FUTURE_VERSION; - - world.maps.readFromParcel(src, world, header.fileversion); - world.model = new ModelContainer(src, world, header.fileversion); - src.close(); - - onWorldLoaded(world); - - return LOAD_RESULT_SUCCESS; - } - - private static void onWorldLoaded(WorldContext world) { - ActorStatsController.recalculatePlayerStats(world.model.player); - Controller.resetMapsNotRecentlyVisited(world); - MovementController.moveBlockedActors(world); - } - - public static FileHeader quickload(Context androidContext, int slot) { - try { - if (slot != SLOT_QUICKSAVE) { - File f = getSlotFile(slot); - if (!f.exists()) return null; - } - FileInputStream fos = getInputFile(androidContext, slot); - DataInputStream src = new DataInputStream(fos); - final FileHeader header = new FileHeader(src); - src.close(); - fos.close(); - return header; - } catch (Exception e) { - return null; - } - } - - private static final Pattern savegameFilenamePattern = Pattern.compile(Constants.FILENAME_SAVEGAME_FILENAME_PREFIX + "(\\d+)"); - public static List getUsedSavegameSlots(Context androidContext) { - try { - final List result = new ArrayList(); - getSavegameDirectory().listFiles(new FilenameFilter() { - @Override - public boolean accept(File f, String filename) { - Matcher m = savegameFilenamePattern.matcher(filename); - if (m != null && m.matches()) { - result.add(Integer.parseInt(m.group(1))); - return true; - } - return false; - } - }); - Collections.sort(result); - return result; - } catch (Exception e) { - return null; - } - } - - public static final class FileHeader { - public final int fileversion; - public final String playerName; - public final String displayInfo; - - public FileHeader(String playerName, String displayInfo) { - this.fileversion = AndorsTrailApplication.CURRENT_VERSION; - this.playerName = playerName; - this.displayInfo = displayInfo; - } - - public String describe() { - return playerName + ", " + displayInfo; - } - - - // ====== PARCELABLE =================================================================== - - public FileHeader(DataInputStream src) throws IOException { - int fileversion = src.readInt(); - if (fileversion == 11) fileversion = 5; // Fileversion 5 had no version identifier, but the first byte was 11. - this.fileversion = fileversion; - if (fileversion >= 14) { // Before fileversion 14 (0.6.7), we had no file header. - this.playerName = src.readUTF(); - this.displayInfo = src.readUTF(); - } else { - this.playerName = null; - this.displayInfo = null; - } - } - - public static void writeToParcel(DataOutputStream dest, String playerName, String displayInfo) throws IOException { - dest.writeInt(AndorsTrailApplication.CURRENT_VERSION); - dest.writeUTF(playerName); - dest.writeUTF(displayInfo); - } - } -} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/VisualEffectCollection.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/VisualEffectCollection.java index 7874fb0d8..f55f9679f 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/VisualEffectCollection.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/VisualEffectCollection.java @@ -1,8 +1,6 @@ package com.gpl.rpg.AndorsTrail; import android.graphics.Color; - -import com.gpl.rpg.AndorsTrail.R; import com.gpl.rpg.AndorsTrail.resource.DynamicTileLoader; import com.gpl.rpg.AndorsTrail.util.ConstRange; @@ -30,7 +28,7 @@ public final class VisualEffectCollection { return new VisualEffect(frameIconIDs, duration, textColor); } - public final static class VisualEffect { + public static final class VisualEffect { public final int[] frameIconIDs; public final int duration; // milliseconds public final int textColor; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/WorldSetup.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/WorldSetup.java index bbb813768..cca4a3d24 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/WorldSetup.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/WorldSetup.java @@ -6,15 +6,16 @@ import android.content.Context; import android.content.res.Resources; import android.os.AsyncTask; +import com.gpl.rpg.AndorsTrail.context.ViewContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; -import com.gpl.rpg.AndorsTrail.controller.Controller; -import com.gpl.rpg.AndorsTrail.controller.MovementController; import com.gpl.rpg.AndorsTrail.model.ModelContainer; import com.gpl.rpg.AndorsTrail.resource.ResourceLoader; +import com.gpl.rpg.AndorsTrail.savegames.Savegames; public final class WorldSetup { private final WorldContext world; + private final ViewContext view; private final WeakReference androidContext; private boolean isResourcesInitialized = false; private boolean isInitializingResources = false; @@ -28,8 +29,9 @@ public final class WorldSetup { public String newHeroName; private int loadResult; - public WorldSetup(WorldContext world, Context androidContext) { + public WorldSetup(WorldContext world, ViewContext view, Context androidContext) { this.world = world; + this.view = view; this.androidContext = new WeakReference(androidContext); } @@ -44,7 +46,7 @@ public final class WorldSetup { } } - public void startResourceLoader(final Resources r, final AndorsTrailPreferences preferences) { + public void startResourceLoader(final Resources r) { if (isResourcesInitialized) return; synchronized (this) { @@ -137,9 +139,9 @@ public final class WorldSetup { private int continueWorld() { Context ctx = androidContext.get(); - int result = Savegames.loadWorld(world, ctx, loadFromSlot); + int result = Savegames.loadWorld(world, view, ctx, loadFromSlot); if (result == Savegames.LOAD_RESULT_SUCCESS) { - MovementController.cacheCurrentMapData(ctx.getResources(), world, world.model.currentMap); + view.movementController.cacheCurrentMapData(ctx.getResources(), world.model.currentMap); } return result; } @@ -148,8 +150,10 @@ public final class WorldSetup { Context ctx = androidContext.get(); world.model = new ModelContainer(); world.model.player.initializeNewPlayer(world.itemTypes, world.dropLists, newHeroName); - MovementController.respawnPlayer(ctx.getResources(), world); - Controller.playerRested(world, null); + + view.actorStatsController.recalculatePlayerStats(world.model.player); + view.movementController.respawnPlayer(ctx.getResources()); + view.controller.lotsOfTimePassed(); } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/AboutActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/AboutActivity.java index 1f1a13ed3..b95736f9f 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/AboutActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/AboutActivity.java @@ -23,7 +23,7 @@ public final class AboutActivity extends Activity implements ImageGetter { super.onCreate(savedInstanceState); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); - AndorsTrailApplication.setWindowParameters(this, app.preferences); + app.setWindowParameters(this); setContentView(R.layout.about); final Resources res = getResources(); @@ -67,7 +67,7 @@ public final class AboutActivity extends Activity implements ImageGetter { tv.setMovementMethod(LinkMovementMethod.getInstance()); TextView t = (TextView) findViewById(R.id.about_version); - t.setText("v" + AndorsTrailApplication.CURRENT_VERSION_DISPLAY); + t.setText('v' + AndorsTrailApplication.CURRENT_VERSION_DISPLAY); } @Override @@ -78,12 +78,13 @@ public final class AboutActivity extends Activity implements ImageGetter { Drawable r = res.getDrawable(R.drawable.ui_quickslots); r.setBounds(0, 0, r.getIntrinsicWidth(), r.getIntrinsicHeight()); return r; - } else if (s.equals("char_hero.png")) { + } + if (s.equals("char_hero.png")) { Drawable r = res.getDrawable(R.drawable.char_hero); r.setBounds(0, 0, r.getIntrinsicWidth(), r.getIntrinsicHeight()*4/5); return r; } - else if (s.equals("monster.png")) d = res.getDrawable(R.drawable.monsters_eye4); + if (s.equals("monster.png")) d = res.getDrawable(R.drawable.monsters_eye4); else if (s.equals("flee_example.png")) d = res.getDrawable(R.drawable.ui_flee_example); else if (s.equals("doubleattackexample.png")) d = res.getDrawable(R.drawable.ui_doubleattackexample); else return null; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ActorConditionInfoActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ActorConditionInfoActivity.java index f47dfe860..4790413f7 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ActorConditionInfoActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ActorConditionInfoActivity.java @@ -17,7 +17,7 @@ import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionType; import com.gpl.rpg.AndorsTrail.view.AbilityModifierInfoView; import com.gpl.rpg.AndorsTrail.view.ItemEffectsView_OnUse; -public class ActorConditionInfoActivity extends Activity { +public final class ActorConditionInfoActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { @@ -25,9 +25,9 @@ public class ActorConditionInfoActivity extends Activity { AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } requestWindowFeature(Window.FEATURE_NO_TITLE); - final WorldContext world = app.world; + final WorldContext world = app.getWorld(); - String conditionTypeID = getIntent().getData().getLastPathSegment().toString(); + String conditionTypeID = getIntent().getData().getLastPathSegment(); ActorConditionType conditionType = world.actorConditionsTypes.getActorConditionType(conditionTypeID); setContentView(R.layout.actorconditioninfo); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/BulkSelectionInterface.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/BulkSelectionInterface.java index b155d5df7..11d593c29 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/BulkSelectionInterface.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/BulkSelectionInterface.java @@ -28,32 +28,33 @@ import com.gpl.rpg.AndorsTrail.model.item.ItemType; * @author ejwessel * Creates the BulkSelectionInterface dialog that allows for buy/drop/selling */ -public class BulkSelectionInterface extends Activity implements TextWatcher { +public final class BulkSelectionInterface extends Activity implements TextWatcher { // class variables - final public static int BULK_INTERFACE_BUY = 0; - final public static int BULK_INTERFACE_SELL = 1; - final public static int BULK_INTERFACE_DROP = 2; + public static final int BULK_INTERFACE_BUY = 0; + public static final int BULK_INTERFACE_SELL = 1; + public static final int BULK_INTERFACE_DROP = 2; - final private static int BUTTON_REPEAT_FIRST_TIME = 300; // Delay after the touch before the counting starts - final private static int BUTTON_REPEAT_FURTHER_TIMES = 50; // Delay between two count events - final private static int BUTTON_REPEAT_DOUBLE_AFTER = 10; // after how many count events the countValue doubles? + private static final int BUTTON_REPEAT_FIRST_TIME = 300; // Delay after the touch before the counting starts + private static final int BUTTON_REPEAT_FURTHER_TIMES = 50; // Delay between two count events + private static final int BUTTON_REPEAT_DOUBLE_AFTER = 10; // after how many count events the countValue doubles? private WorldContext world; private int interfaceType; // the type of interface either: BULK_INTERFACE_BUY, BULK_INTERFACE_SELL or BULK_INTERFACE_DROP private ItemType itemType; private int totalAvailableAmount; private int pricePerUnit; - - private TextView bulkselection_amount_available; + private TextView bulkselection_summary_totalgold; private EditText bulkselection_amount_taken; // the amount we're going to take from the totalAmount private SeekBar bulkselection_slider; private Button okButton; private final Handler timedEventHandler = new Handler(); // variables to count up or down on long presses on the buttons - private int countValue, countTime; + private int countValue; + private int countTime; private final Runnable countEvent = new Runnable() { + @Override public void run() { incrementValueAndRepeat(BUTTON_REPEAT_FURTHER_TIMES); } @@ -73,8 +74,8 @@ public class BulkSelectionInterface extends Activity implements TextWatcher { super.onCreate(savedInstanceState); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - this.world = app.world; - AndorsTrailApplication.setWindowParameters(this, app.preferences); + this.world = app.getWorld(); + app.setWindowParameters(this); final Resources res = getResources(); @@ -92,7 +93,7 @@ public class BulkSelectionInterface extends Activity implements TextWatcher { // initialize UI variables TextView bulkselection_action_type = (TextView)findViewById(R.id.bulkselection_action_type); bulkselection_amount_taken = (EditText)findViewById(R.id.bulkselection_amount_taken); - bulkselection_amount_available = (TextView)findViewById(R.id.bulkselection_amount_available); + TextView bulkselection_amount_available = (TextView) findViewById(R.id.bulkselection_amount_available); bulkselection_slider = (SeekBar)findViewById(R.id.bulkselection_slider); bulkselection_summary_totalgold = (TextView)findViewById(R.id.bulkselection_summary_totalgold); okButton = (Button)findViewById(R.id.bulkselection_finalize_button); @@ -122,7 +123,7 @@ public class BulkSelectionInterface extends Activity implements TextWatcher { // initialize the visual components visuals okButton.setText(actionText); - bulkselection_action_type.setText(actionText + " "); + bulkselection_action_type.setText(actionText + ' '); bulkselection_amount_available.setText(Integer.toString(totalAvailableAmount)); bulkselection_slider.setMax(totalAvailableAmount - 1); @@ -188,7 +189,7 @@ public class BulkSelectionInterface extends Activity implements TextWatcher { okButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (requiresConfirmation(itemType)) { + if (requiresConfirmation()) { final String displayType = ItemInfoActivity.getDisplayTypeString(res, itemType).toLowerCase(); final String message = res.getString(R.string.bulkselection_sell_confirmation, itemType.getName(world.model.player), displayType); @@ -201,7 +202,7 @@ public class BulkSelectionInterface extends Activity implements TextWatcher { public void onClick(DialogInterface dialog, int which) { itemsResult(intent); } - }) + }) .setNegativeButton(android.R.string.no, null) .show(); } else { @@ -209,7 +210,7 @@ public class BulkSelectionInterface extends Activity implements TextWatcher { } } - private boolean requiresConfirmation(ItemType itemType) { + private boolean requiresConfirmation() { if (interfaceType != BULK_INTERFACE_SELL) return false; if (itemType.isOrdinaryItem()) return false; return true; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ConversationActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ConversationActivity.java index 2ae2d172a..2521bd34a 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ConversationActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ConversationActivity.java @@ -31,6 +31,7 @@ import android.widget.TextView.BufferType; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.Dialogs; 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.ConversationController; import com.gpl.rpg.AndorsTrail.conversation.ConversationCollection; @@ -49,6 +50,7 @@ public final class ConversationActivity extends Activity implements OnKeyListene private static final int NPCConversationColor = Color.argb(255, 0xbb, 0xbb, 0x22); private WorldContext world; + private ViewContext view; private Player player; private String phraseID; private Phrase phrase; @@ -71,7 +73,8 @@ public final class ConversationActivity extends Activity implements OnKeyListene super.onCreate(savedInstanceState); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - this.world = app.world; + this.world = app.getWorld(); + this.view = app.getViewContext(); this.player = world.model.player; requestWindowFeature(Window.FEATURE_NO_TITLE); @@ -239,7 +242,7 @@ public final class ConversationActivity extends Activity implements OnKeyListene Loot loot = null; if (applyPhraseRewards) { - loot = ConversationController.applyPhraseRewards(player, phrase, world); + loot = view.conversationController.applyPhraseRewards(player, phrase); } if (phrase.message == null) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/DebugInterface.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/DebugInterface.java index d3e5c845e..c214105d9 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/DebugInterface.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/DebugInterface.java @@ -20,11 +20,11 @@ public final class DebugInterface { private final Resources res; private final WorldContext world; - public DebugInterface(ViewContext viewContext) { - this.viewContext = viewContext; - this.mainActivity = viewContext.mainActivity; - this.world = viewContext; + public DebugInterface(ViewContext view, WorldContext world, MainActivity mainActivity) { + this.viewContext = view; + this.world = world; this.res = mainActivity.getResources(); + this.mainActivity = mainActivity; } public void addDebugButtons() { @@ -37,7 +37,6 @@ public final class DebugInterface { world.model.player.damagePotential.set(99, 99); world.model.player.attackChance = 200; world.model.player.attackCost = 1; - mainActivity.updateStatus(); mainActivity.showToast("DEBUG: damagePotential=99, chance=200%, cost=1", Toast.LENGTH_SHORT); } }) @@ -129,9 +128,8 @@ public final class DebugInterface { public void onClick(View arg0) { world.model.player.baseTraits.maxHP = 200; world.model.player.health.max = world.model.player.baseTraits.maxHP; - world.model.player.setMaxHP(); + viewContext.actorStatsController.setActorMaxHealth(world.model.player); world.model.player.conditions.clear(); - mainActivity.updateStatus(); mainActivity.showToast("DEBUG: hp set to max", Toast.LENGTH_SHORT); } }) diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/DisplayWorldMapActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/DisplayWorldMapActivity.java index cfe9efae5..704b11d1e 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/DisplayWorldMapActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/DisplayWorldMapActivity.java @@ -19,7 +19,7 @@ import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment; import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.WorldMapSegmentMap; import com.gpl.rpg.AndorsTrail.util.L; -public class DisplayWorldMapActivity extends Activity { +public final class DisplayWorldMapActivity extends Activity { private WorldContext world; private WebView displayworldmap_webview; @@ -31,9 +31,9 @@ public class DisplayWorldMapActivity extends Activity { AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - this.world = app.world; + this.world = app.getWorld(); - AndorsTrailApplication.setWindowParameters(this, app.preferences); + app.setWindowParameters(this); setContentView(R.layout.displayworldmap); @@ -76,9 +76,9 @@ public class DisplayWorldMapActivity extends Activity { WorldMapSegmentMap map = segment.maps.get(world.model.currentMap.name); if (map == null) this.finish(); - String url = "file://" + worldmap.getAbsolutePath() + "?" + String url = "file://" + worldmap.getAbsolutePath() + '?' + (world.model.player.position.x + map.worldPosition.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE - + "," + + ',' + (world.model.player.position.y + map.worldPosition.y-1) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE; L.log("Showing " + url); displayworldmap_webview.loadUrl(url); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity.java index 78ff6e2a6..1fe951994 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity.java @@ -20,9 +20,9 @@ public final class HeroinfoActivity extends ActivityGroup { super.onCreate(savedInstanceState); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - this.world = app.world; + this.world = app.getWorld(); - AndorsTrailApplication.setWindowParameters(this, app.preferences); + app.setWindowParameters(this); setContentView(R.layout.heroinfo); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Inventory.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Inventory.java index 8c6db50d0..a71d2331a 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Inventory.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Inventory.java @@ -35,11 +35,9 @@ public final class HeroinfoActivity_Inventory extends Activity { private TileCollection wornTiles; private Player player; - private ItemContainer container; private ItemContainerAdapter inventoryListAdapter; - private ListView inventoryList; - private TextView heroinfo_stats_gold; + private TextView heroinfo_stats_gold; private TextView heroinfo_stats_attack; private TextView heroinfo_stats_defense; @@ -53,22 +51,22 @@ public final class HeroinfoActivity_Inventory extends Activity { super.onCreate(savedInstanceState); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - this.world = app.world; - this.view = app.currentView.get(); + this.world = app.getWorld(); + this.view = app.getViewContext(); this.player = world.model.player; setContentView(R.layout.heroinfo_inventory); - - inventoryList = (ListView) findViewById(R.id.inventorylist_root); + + ListView inventoryList = (ListView) findViewById(R.id.inventorylist_root); registerForContextMenu(inventoryList); inventoryList.setOnItemClickListener(new OnItemClickListener() { @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { + public void onItemClick(AdapterView parent, View v, int position, long id) { ItemType itemType = inventoryListAdapter.getItem(position).itemType; showInventoryItemInfo(itemType.id); } }); - container = player.inventory; + ItemContainer container = player.inventory; wornTiles = world.tileManager.loadTilesFor(player.inventory, getResources()); inventoryListAdapter = new ItemContainerAdapter(this, world.tileManager, container, player, wornTiles); inventoryList.setAdapter(inventoryListAdapter); @@ -95,17 +93,17 @@ public final class HeroinfoActivity_Inventory extends Activity { } private void setWearSlot(final int inventorySlot, int viewId, int resourceId) { - final ImageView view = (ImageView) findViewById(viewId); - wornItemImage[inventorySlot] = view; + final ImageView imageView = (ImageView) findViewById(viewId); + wornItemImage[inventorySlot] = imageView; defaultWornItemImageResourceIDs[inventorySlot] = resourceId; - view.setOnClickListener(new OnClickListener() { + imageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (player.inventory.isEmptySlot(inventorySlot)) return; - view.setClickable(false); // Will be enabled again on update() + imageView.setClickable(false); // Will be enabled again on update() showEquippedItemInfo(player.inventory.wear[inventorySlot], inventorySlot); } - }); + }); } @Override @@ -120,7 +118,7 @@ public final class HeroinfoActivity_Inventory extends Activity { if (actionType == ItemInfoActivity.ITEMACTION_UNEQUIP) { view.itemController.unequipSlot(itemType, data.getExtras().getInt("inventorySlot")); } else if (actionType == ItemInfoActivity.ITEMACTION_EQUIP) { - int slot = suggestInventorySlot(itemType, player); + int slot = suggestInventorySlot(itemType); view.itemController.equipItem(itemType, slot); } else if (actionType == ItemInfoActivity.ITEMACTION_USE) { view.itemController.useItem(itemType); @@ -136,13 +134,12 @@ public final class HeroinfoActivity_Inventory extends Activity { } } - private static int suggestInventorySlot(ItemType itemType, Player player) { + private int suggestInventorySlot(ItemType itemType) { int slot = itemType.category.inventorySlot; if (player.inventory.isEmptySlot(slot)) return slot; - if (slot == Inventory.WEARSLOT_LEFTRING) { - return Inventory.WEARSLOT_RIGHTRING; - } else if (itemType.isOffhandCapableWeapon()) { + if (slot == Inventory.WEARSLOT_LEFTRING) return Inventory.WEARSLOT_RIGHTRING; + if (itemType.isOffhandCapableWeapon()) { ItemType mainWeapon = player.inventory.wear[Inventory.WEARSLOT_WEAPON]; if (mainWeapon != null && mainWeapon.isTwohandWeapon()) return slot; else if (player.inventory.isEmptySlot(Inventory.WEARSLOT_SHIELD)) return Inventory.WEARSLOT_SHIELD; @@ -164,7 +161,7 @@ public final class HeroinfoActivity_Inventory extends Activity { private void updateTraits() { heroinfo_stats_gold.setText(getResources().getString(R.string.heroinfo_gold, player.inventory.gold)); - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(10); ItemController.describeAttackEffect( player.getAttackChance(), player.getDamagePotential().current, @@ -174,7 +171,7 @@ public final class HeroinfoActivity_Inventory extends Activity { sb); heroinfo_stats_attack.setText(sb.toString()); - sb = new StringBuilder(); + sb = new StringBuilder(10); ItemController.describeBlockEffect(player.getBlockChance(), player.getDamageResistance(), sb); heroinfo_stats_defense.setText(sb.toString()); } @@ -185,13 +182,13 @@ public final class HeroinfoActivity_Inventory extends Activity { } } - private void updateWornImage(ImageView view, int resourceIDEmptyImage, ItemType type) { + private void updateWornImage(ImageView imageView, int resourceIDEmptyImage, ItemType type) { if (type != null) { - world.tileManager.setImageViewTile(view, type, wornTiles); + world.tileManager.setImageViewTile(imageView, type, wornTiles); } else { - view.setImageResource(resourceIDEmptyImage); + imageView.setImageResource(resourceIDEmptyImage); } - view.setClickable(true); + imageView.setClickable(true); } private void updateItemList() { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Quests.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Quests.java index 3349027ab..9e990767c 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Quests.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Quests.java @@ -17,6 +17,7 @@ import android.widget.AdapterView.OnItemSelectedListener; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.R; +import com.gpl.rpg.AndorsTrail.context.WorldContext; import com.gpl.rpg.AndorsTrail.model.actor.Player; import com.gpl.rpg.AndorsTrail.model.quest.Quest; import com.gpl.rpg.AndorsTrail.model.quest.QuestCollection; @@ -39,9 +40,10 @@ public final class HeroinfoActivity_Quests extends Activity { final AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - AndorsTrailApplication.setWindowParameters(this, app.preferences); - this.questCollection = app.world.quests; - this.player = app.world.model.player; + app.setWindowParameters(this); + final WorldContext world = app.getWorld(); + this.questCollection = world.quests; + this.player = world.model.player; setContentView(R.layout.questlog); @@ -52,14 +54,14 @@ public final class HeroinfoActivity_Quests extends Activity { questlog_includecompleted.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) { - app.world.model.uiSelections.selectedQuestFilter = questlog_includecompleted.getSelectedItemPosition(); + world.model.uiSelections.selectedQuestFilter = questlog_includecompleted.getSelectedItemPosition(); reloadQuests(); } @Override public void onNothingSelected(AdapterView arg0) {} }); - questlog_includecompleted.setSelection(app.world.model.uiSelections.selectedQuestFilter); + questlog_includecompleted.setSelection(world.model.uiSelections.selectedQuestFilter); ExpandableListView questlog_contents = (ExpandableListView) findViewById(R.id.questlog_contents); questlog_contents_adapter = new SimpleExpandableListAdapter( diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Skills.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Skills.java index d9df87740..8354a5e53 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Skills.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Skills.java @@ -1,24 +1,24 @@ package com.gpl.rpg.AndorsTrail.activity; -import com.gpl.rpg.AndorsTrail.Dialogs; -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.actor.Player; -import com.gpl.rpg.AndorsTrail.view.SkillListAdapter; - import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.TextView; -import android.widget.AdapterView.OnItemClickListener; +import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; +import com.gpl.rpg.AndorsTrail.Dialogs; +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.model.actor.Player; +import com.gpl.rpg.AndorsTrail.view.SkillListAdapter; public final class HeroinfoActivity_Skills extends Activity { private WorldContext world; + private ViewContext view; private Player player; @@ -29,7 +29,8 @@ public final class HeroinfoActivity_Skills extends Activity { super.onCreate(savedInstanceState); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - this.world = app.world; + this.world = app.getWorld(); + this.view = app.getViewContext(); this.player = world.model.player; setContentView(R.layout.heroinfo_skill_list); @@ -39,7 +40,7 @@ public final class HeroinfoActivity_Skills extends Activity { skillList.setAdapter(skillListAdapter); skillList.setOnItemClickListener(new OnItemClickListener() { @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { + public void onItemClick(AdapterView parent, View v, int position, long id) { Dialogs.showSkillInfo(HeroinfoActivity_Skills.this, (int) id); } }); @@ -59,7 +60,7 @@ public final class HeroinfoActivity_Skills extends Activity { if (resultCode != RESULT_OK) break; int skillID = data.getExtras().getInt("skillID"); - SkillController.levelUpSkillManually(player, world.skills.getSkill(skillID)); + view.skillController.levelUpSkillManually(player, world.skills.getSkill(skillID)); break; } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Stats.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Stats.java index befcb3b0d..5367999b5 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Stats.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Stats.java @@ -25,8 +25,7 @@ import android.widget.TableLayout; import android.widget.TextView; public final class HeroinfoActivity_Stats extends Activity { - private WorldContext world; - + private Player player; private Button levelUpButton; @@ -50,7 +49,7 @@ public final class HeroinfoActivity_Stats extends Activity { super.onCreate(savedInstanceState); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - this.world = app.world; + final WorldContext world = app.getWorld(); this.player = world.model.player; setContentView(R.layout.heroinfo_stats); @@ -114,15 +113,15 @@ public final class HeroinfoActivity_Stats extends Activity { private void updateTraits() { heroinfo_level.setText(Integer.toString(player.getLevel())); heroinfo_totalexperience.setText(Integer.toString(player.getTotalExperience())); - heroinfo_ap.setText(player.ap.toString()); + heroinfo_ap.setText(player.getMaxAP() + "/" + player.getCurrentAP()); 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); + rangebar_hp.update(player.getMaxHP(), player.getCurrentHP()); + rangebar_exp.update(player.getMaxLevelExperience(), player.getCurrentLevelExperience()); TraitsInfoView.update(heroinfo_container, player); TraitsInfoView.updateTraitsTable( diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ItemInfoActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ItemInfoActivity.java index bd0d4d90e..067850123 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ItemInfoActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ItemInfoActivity.java @@ -1,7 +1,5 @@ package com.gpl.rpg.AndorsTrail.activity; -import java.util.Arrays; - import android.app.Activity; import android.content.Intent; import android.content.res.Resources; @@ -10,13 +8,14 @@ import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; - import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.R; import com.gpl.rpg.AndorsTrail.context.WorldContext; import com.gpl.rpg.AndorsTrail.model.item.ItemType; import com.gpl.rpg.AndorsTrail.view.ItemEffectsView; +import java.util.Collections; + public final class ItemInfoActivity extends Activity { public static int ITEMACTION_NONE = 1; @@ -25,17 +24,15 @@ public final class ItemInfoActivity extends Activity { public static int ITEMACTION_UNEQUIP = 4; public static int ITEMACTION_BUY = 5; public static int ITEMACTION_SELL = 6; - - private WorldContext world; - - @Override + + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - this.world = app.world; + final WorldContext world = app.getWorld(); - AndorsTrailApplication.setWindowParameters(this, app.preferences); + app.setWindowParameters(this); final Intent intent = getIntent(); Bundle params = intent.getExtras(); @@ -55,9 +52,9 @@ public final class ItemInfoActivity extends Activity { ((ItemEffectsView) findViewById(R.id.iteminfo_effects)).update( itemType.effects_equip, - itemType.effects_use == null ? null : Arrays.asList(itemType.effects_use), - itemType.effects_hit == null ? null : Arrays.asList(itemType.effects_hit), - itemType.effects_kill == null ? null : Arrays.asList(itemType.effects_kill), + itemType.effects_use == null ? null : Collections.singletonList(itemType.effects_use), + itemType.effects_hit == null ? null : Collections.singletonList(itemType.effects_hit), + itemType.effects_kill == null ? null : Collections.singletonList(itemType.effects_kill), itemType.isWeapon() ); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/LevelUpActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/LevelUpActivity.java index 973bdbc28..b70bbf608 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/LevelUpActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/LevelUpActivity.java @@ -11,26 +11,27 @@ import android.widget.TextView; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; 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.ActorStatsController; import com.gpl.rpg.AndorsTrail.controller.Constants; -import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection; import com.gpl.rpg.AndorsTrail.model.actor.Player; public final class LevelUpActivity extends Activity { private WorldContext world; + private ViewContext view; private Player player; private TextView levelup_description; private TextView levelup_title; private View levelup_adds_new_skillpoint; - /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - this.world = app.world; + this.world = app.getWorld(); + this.view = app.getViewContext(); this.player = world.model.player; requestWindowFeature(Window.FEATURE_NO_TITLE); @@ -47,7 +48,7 @@ public final class LevelUpActivity extends Activity { b.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { - levelup(SELECT_HEALTH); + levelup(ActorStatsController.LEVELUP_HEALTH); } }); b.setText(getString(R.string.levelup_add_health, Constants.LEVELUP_EFFECT_HEALTH)); @@ -56,7 +57,7 @@ public final class LevelUpActivity extends Activity { b.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { - levelup(SELECT_ATK_CH); + levelup(ActorStatsController.LEVELUP_ATTACK_CHANCE); } }); b.setText(getString(R.string.levelup_add_attackchance, Constants.LEVELUP_EFFECT_ATK_CH)); @@ -65,7 +66,7 @@ public final class LevelUpActivity extends Activity { b.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { - levelup(SELECT_ATK_DMG); + levelup(ActorStatsController.LEVELUP_ATTACK_DAMAGE); } }); b.setText(getString(R.string.levelup_add_attackdamage, Constants.LEVELUP_EFFECT_ATK_DMG)); @@ -74,7 +75,7 @@ public final class LevelUpActivity extends Activity { b.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { - levelup(SELECT_DEF_CH); + levelup(ActorStatsController.LEVELUP_BLOCK_CHANCE); } }); b.setText(getString(R.string.levelup_add_blockchance, Constants.LEVELUP_EFFECT_DEF_CH)); @@ -99,45 +100,10 @@ public final class LevelUpActivity extends Activity { } } - private static final int SELECT_HEALTH = 0; - private static final int SELECT_ATK_CH = 1; - private static final int SELECT_ATK_DMG = 2; - private static final int SELECT_DEF_CH = 3; - public void levelup(int selectionID) { if (LevelUpActivity.this.isFinishing()) return; - addLevelupEffect(player, selectionID); - LevelUpActivity.this.finish(); - } - - public static void addLevelupEffect(Player player, int selectionID) { - int hpIncrease = 0; - switch (selectionID) { - case SELECT_HEALTH: - hpIncrease = Constants.LEVELUP_EFFECT_HEALTH; - break; - case SELECT_ATK_CH: - player.baseTraits.attackChance += Constants.LEVELUP_EFFECT_ATK_CH; - break; - case SELECT_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.baseTraits.blockChance += Constants.LEVELUP_EFFECT_DEF_CH; - break; - } - if (player.nextLevelAddsNewSkillpoint()) { - player.availableSkillIncreases++; - } - player.level++; - - hpIncrease += player.getSkillLevel(SkillCollection.SKILL_FORTITUDE) * SkillCollection.PER_SKILLPOINT_INCREASE_FORTITUDE_HEALTH; - player.health.max += hpIncrease; - player.baseTraits.maxHP += hpIncrease; - player.health.current += hpIncrease; - - ActorStatsController.recalculatePlayerStats(player); + view.actorStatsController.addLevelupEffect(player, selectionID); + finish(); } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/LoadSaveActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/LoadSaveActivity.java index 563df2ee0..8c076e59a 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/LoadSaveActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/LoadSaveActivity.java @@ -18,8 +18,8 @@ import android.widget.TextView; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences; import com.gpl.rpg.AndorsTrail.R; -import com.gpl.rpg.AndorsTrail.Savegames; -import com.gpl.rpg.AndorsTrail.Savegames.FileHeader; +import com.gpl.rpg.AndorsTrail.savegames.Savegames; +import com.gpl.rpg.AndorsTrail.savegames.Savegames.FileHeader; import com.gpl.rpg.AndorsTrail.model.ModelContainer; public final class LoadSaveActivity extends Activity implements OnClickListener { @@ -34,11 +34,11 @@ public final class LoadSaveActivity extends Activity implements OnClickListener super.onCreate(savedInstanceState); final AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); - AndorsTrailApplication.setWindowParameters(this, app.preferences); - this.model = app.world.model; - this.preferences = app.preferences; + app.setWindowParameters(this); + this.model = app.getWorld().model; + this.preferences = app.getPreferences(); - String loadsave = getIntent().getData().getLastPathSegment().toString(); + String loadsave = getIntent().getData().getLastPathSegment(); isLoading = (loadsave.equalsIgnoreCase("load")); setContentView(R.layout.loadsave); @@ -105,7 +105,8 @@ public final class LoadSaveActivity extends Activity implements OnClickListener if (preferences.displayOverwriteSavegame == AndorsTrailPreferences.CONFIRM_OVERWRITE_SAVEGAME_ALWAYS) { return getString(R.string.loadsave_save_overwrite_confirmation_all); - } else if (preferences.displayOverwriteSavegame == AndorsTrailPreferences.CONFIRM_OVERWRITE_SAVEGAME_NEVER) { + } + if (preferences.displayOverwriteSavegame == AndorsTrailPreferences.CONFIRM_OVERWRITE_SAVEGAME_NEVER) { return null; } @@ -126,7 +127,7 @@ public final class LoadSaveActivity extends Activity implements OnClickListener if (message != null) { final String title = - getString(R.string.loadsave_save_overwrite_confirmation_title) + " " + getString(R.string.loadsave_save_overwrite_confirmation_title) + ' ' + getString(R.string.loadsave_save_overwrite_confirmation_slot, slot); new AlertDialog.Builder(this) .setIcon(android.R.drawable.ic_dialog_alert) diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/LoadingActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/LoadingActivity.java index abd411f5e..dbda91a13 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/LoadingActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/LoadingActivity.java @@ -11,7 +11,7 @@ import android.os.Bundle; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.R; -import com.gpl.rpg.AndorsTrail.Savegames; +import com.gpl.rpg.AndorsTrail.savegames.Savegames; import com.gpl.rpg.AndorsTrail.WorldSetup; import com.gpl.rpg.AndorsTrail.WorldSetup.OnResourcesLoadedListener; import com.gpl.rpg.AndorsTrail.WorldSetup.OnSceneLoadedListener; @@ -27,8 +27,8 @@ public final class LoadingActivity extends Activity implements OnResourcesLoaded public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); - AndorsTrailApplication.setWindowParameters(this, app.preferences); - this.setup = app.setup; + app.setWindowParameters(this); + this.setup = app.getWorldSetup(); } @Override diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MainActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MainActivity.java index 44491a7e8..941dc6528 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MainActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MainActivity.java @@ -1,19 +1,28 @@ package com.gpl.rpg.AndorsTrail.activity; import java.lang.ref.WeakReference; +import java.util.Collection; import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences; import com.gpl.rpg.AndorsTrail.Dialogs; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.R; -import com.gpl.rpg.AndorsTrail.Savegames; +import com.gpl.rpg.AndorsTrail.savegames.Savegames; import com.gpl.rpg.AndorsTrail.context.ViewContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; import com.gpl.rpg.AndorsTrail.controller.CombatController; import com.gpl.rpg.AndorsTrail.controller.MovementController; +import com.gpl.rpg.AndorsTrail.controller.listeners.CombatActionListener; +import com.gpl.rpg.AndorsTrail.controller.listeners.CombatTurnListener; +import com.gpl.rpg.AndorsTrail.controller.listeners.PlayerMovementListener; +import com.gpl.rpg.AndorsTrail.controller.listeners.WorldEventListener; +import com.gpl.rpg.AndorsTrail.model.AttackResult; import com.gpl.rpg.AndorsTrail.model.actor.Monster; import com.gpl.rpg.AndorsTrail.model.actor.Player; import com.gpl.rpg.AndorsTrail.model.item.ItemContainer.ItemEntry; +import com.gpl.rpg.AndorsTrail.model.item.Loot; +import com.gpl.rpg.AndorsTrail.model.map.MapObject; +import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; import com.gpl.rpg.AndorsTrail.util.Coord; import com.gpl.rpg.AndorsTrail.view.CombatView; import com.gpl.rpg.AndorsTrail.view.DisplayActiveActorConditionIcons; @@ -39,7 +48,7 @@ import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; -public final class MainActivity extends Activity { +public final class MainActivity extends Activity implements PlayerMovementListener, CombatActionListener, CombatTurnListener, WorldEventListener { public static final int INTENTREQUEST_MONSTERENCOUNTER = 2; public static final int INTENTREQUEST_ITEMINFO = 3; @@ -76,17 +85,17 @@ public final class MainActivity extends Activity { AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - this.world = app.world; - this.view = new ViewContext(app, this); - app.currentView = new WeakReference(this.view); - AndorsTrailApplication.setWindowParameters(this, app.preferences); + AndorsTrailPreferences preferences = app.getPreferences(); + this.world = app.getWorld(); + this.view = app.getViewContext(); + app.setWindowParameters(this); setContentView(R.layout.main); mainview = (MainView) findViewById(R.id.main_mainview); statusview = (StatusView) findViewById(R.id.main_statusview); combatview = (CombatView) findViewById(R.id.main_combatview); quickitemview = (QuickitemView) findViewById(R.id.main_quickitemview); - activeConditions = new DisplayActiveActorConditionIcons(app.preferences, world.tileManager, this, (RelativeLayout) findViewById(R.id.statusview_activeconditions)); + activeConditions = new DisplayActiveActorConditionIcons(view, world, this, (RelativeLayout) findViewById(R.id.statusview_activeconditions)); dpad = (VirtualDpadView) findViewById(R.id.main_virtual_dpad); toolboxview = (ToolboxView) findViewById(R.id.main_toolboxview); statusview.registerToolboxViews(toolboxview, quickitemview); @@ -100,12 +109,13 @@ public final class MainActivity extends Activity { }); clearMessages(); - if (AndorsTrailApplication.DEVELOPMENT_DEBUGBUTTONS) new DebugInterface(view).addDebugButtons(); + if (AndorsTrailApplication.DEVELOPMENT_DEBUGBUTTONS) + new DebugInterface(view, world, this).addDebugButtons(); quickitemview.setVisibility(View.GONE); quickitemview.registerForContextMenu(this); - dpad.updateVisibility(app.preferences); + dpad.updateVisibility(preferences); // Define which views are in front of each other. dpad.bringToFront(); @@ -139,15 +149,15 @@ public final class MainActivity extends Activity { final Coord p = world.model.player.nextPosition; Monster m = world.model.currentMap.getMonsterAt(p); if (m == null) return; - world.model.currentMap.remove(m); - redrawAll(MainView.REDRAW_ALL_MONSTER_KILLED); + view.monsterSpawnController.remove(world.model.currentMap, m); } break; case INTENTREQUEST_PREFERENCES: AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); - AndorsTrailPreferences.read(this, app.preferences); - world.tileManager.updatePreferences(app.preferences); - dpad.updateVisibility(app.preferences); + AndorsTrailPreferences preferences = app.getPreferences(); + AndorsTrailPreferences.read(this, preferences); + world.tileManager.updatePreferences(preferences); + dpad.updateVisibility(preferences); break; case INTENTREQUEST_SAVEGAME: if (resultCode != Activity.RESULT_OK) break; @@ -172,17 +182,17 @@ public final class MainActivity extends Activity { view.gameRoundController.pause(); view.movementController.stopMovement(); - activeConditions.unsubscribe(world); + unsubscribeFromModel(); save(Savegames.SLOT_QUICKSAVE); } - @Override + @Override protected void onResume() { super.onResume(); - if (!AndorsTrailApplication.getApplicationFromActivity(this).setup.isSceneReady) return; + if (!AndorsTrailApplication.getApplicationFromActivity(this).getWorldSetup().isSceneReady) return; - activeConditions.subscribe(world); + subscribeToModelChanges(); view.gameRoundController.resume(); @@ -190,8 +200,33 @@ public final class MainActivity extends Activity { view.combatController.setCombatSelection(world.model.uiSelections.selectedMonster, world.model.uiSelections.selectedPosition); view.combatController.enterCombat(CombatController.BEGIN_TURN_CONTINUE); } + updateStatus(); } + private void unsubscribeFromModel() { + activeConditions.unsubscribe(); + combatview.unsubscribe(); + mainview.unsubscribe(); + quickitemview.unsubscribe(); + statusview.unsubscribe(); + view.movementController.playerMovementListeners.remove(this); + view.combatController.combatActionListeners.remove(this); + view.combatController.combatTurnListeners.remove(this); + view.controller.worldEventListeners.remove(this); + } + + private void subscribeToModelChanges() { + view.controller.worldEventListeners.add(this); + view.combatController.combatTurnListeners.add(this); + view.combatController.combatActionListeners.add(this); + view.movementController.playerMovementListeners.add(this); + statusview.subscribe(); + quickitemview.subscribe(); + mainview.subscribe(); + combatview.subscribe(); + activeConditions.subscribe(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(R.string.exit_to_menu) @@ -208,7 +243,7 @@ public final class MainActivity extends Activity { .setOnMenuItemClickListener(new OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem arg0) { - Dialogs.showSave(MainActivity.this, view); + Dialogs.showSave(MainActivity.this, view, world); return true; } }); @@ -228,12 +263,12 @@ public final class MainActivity extends Activity { public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); if(quickitemview.isQuickButtonId(v.getId())){ - createQuickButtonMenu(menu, v, menuInfo); + createQuickButtonMenu(menu); } lastSelectedMenu = null; } - private void createQuickButtonMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo){ + private void createQuickButtonMenu(ContextMenu menu){ menu.add(Menu.NONE, R.id.quick_menu_unassign, Menu.NONE, R.string.inventory_unassign); SubMenu assignMenu = menu.addSubMenu(Menu.NONE, R.id.quick_menu_assign, Menu.NONE, R.string.inventory_assign); for(int i=0; i 0) { @@ -294,7 +323,7 @@ public final class MainActivity extends Activity { statusText.setVisibility(View.VISIBLE); } - public void clearMessages() { + private void clearMessages() { for(int i = 0; i < NUM_MESSAGES; ++i) { messages[i] = ""; } @@ -313,4 +342,145 @@ public final class MainActivity extends Activity { } t.show(); } + + + @Override + public void onPlayerMoved(Coord newPosition, Coord previousPosition) { } + + @Override + public void onPlayerEnteredNewMap(PredefinedMap map, Coord p) { } + + @Override + public void onCombatStarted() { + clearMessages(); + } + + @Override + public void onCombatEnded() { + clearMessages(); + } + + @Override + public void onPlayerAttackMissed(Monster target, AttackResult attackResult) { + message(getString(R.string.combat_result_heromiss)); + } + + @Override + public void onPlayerAttackSuccess(Monster target, AttackResult attackResult) { + String msg; + final String monsterName = target.getName(); + if (attackResult.isCriticalHit) { + msg = getString(R.string.combat_result_herohitcritical, monsterName, attackResult.damage); + } else { + msg = getString(R.string.combat_result_herohit, monsterName, attackResult.damage); + } + if (attackResult.targetDied) { + msg += ' ' + getString(R.string.combat_result_herokillsmonster, monsterName, attackResult.damage); + } + message(msg); + } + + @Override + public void onMonsterAttackMissed(Monster attacker, AttackResult attackResult) { + message(getString(R.string.combat_result_monstermiss, attacker.getName())); + } + + @Override + public void onMonsterAttackSuccess(Monster attacker, AttackResult attackResult) { + final String monsterName = attacker.getName(); + if (attackResult.isCriticalHit) { + message(getString(R.string.combat_result_monsterhitcritical, monsterName, attackResult.damage)); + } else { + message(getString(R.string.combat_result_monsterhit, monsterName, attackResult.damage)); + } + } + + @Override + public void onPlayerKilledMonster(Monster target) { } + + @Override + public void onNewPlayerTurn() { } + + @Override + public void onMonsterIsAttacking(Monster m) { } + + @Override + public void onPlayerStartedConversation(Monster m, String phraseID) { + Dialogs.showConversation(this, view, phraseID, m); + } + + @Override + public void onPlayerSteppedOnMonster(Monster m) { + Dialogs.showMonsterEncounter(this, view, m); + } + + @Override + public void onPlayerSteppedOnMapSignArea(MapObject area) { + Dialogs.showMapSign(this, view, area.id); + } + + @Override + public void onPlayerSteppedOnKeyArea(MapObject area) { + Dialogs.showKeyArea(this, view, area.id); + } + + @Override + public void onPlayerSteppedOnRestArea(MapObject area) { + Dialogs.showConfirmRest(this, view, area); + } + + @Override + public void onPlayerSteppedOnGroundLoot(Loot loot) { + final String msg = Dialogs.getGroundLootMessage(this, loot); + Dialogs.showGroundLoot(this, view, world, loot, msg); + } + + @Override + public void onPlayerPickedUpGroundLoot(Loot loot) { + if (view.preferences.displayLoot == AndorsTrailPreferences.DISPLAYLOOT_NONE) return; + + final String msg = Dialogs.getGroundLootMessage(this, loot); + showToast(msg, Toast.LENGTH_LONG); + } + + @Override + public void onPlayerFoundMonsterLoot(Collection loot, int exp) { + final Loot combinedLoot = Loot.combine(loot); + final String msg = Dialogs.getMonsterLootMessage(this, combinedLoot, exp); + Dialogs.showMonsterLoot(this, view, world, loot, combinedLoot, msg); + } + + @Override + public void onPlayerPickedUpMonsterLoot(Collection loot, int exp) { + if (view.preferences.displayLoot == AndorsTrailPreferences.DISPLAYLOOT_NONE) return; + + final Loot combinedLoot = Loot.combine(loot); + final String msg = Dialogs.getMonsterLootMessage(this, combinedLoot, exp); + showToast(msg, Toast.LENGTH_LONG); + } + + @Override + public void onPlayerRested() { + Dialogs.showRested(this, view); + } + + @Override + public void onPlayerDied(int lostExp) { + message(getString(R.string.combat_hero_dies, lostExp)); + } + + @Override + public void onPlayerStartedFleeing() { + message(getString(R.string.combat_begin_flee)); + } + + @Override + public void onPlayerFailedFleeing() { + message(getString(R.string.combat_flee_failed)); + } + + @Override + public void onPlayerDoesNotHaveEnoughAP() { + message(getString(R.string.combat_not_enough_ap)); + } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterEncounterActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterEncounterActivity.java index dd8412d9b..b0e898659 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterEncounterActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterEncounterActivity.java @@ -11,18 +11,19 @@ import android.widget.TextView; import com.gpl.rpg.AndorsTrail.Dialogs; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; 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.model.actor.Monster; public final class MonsterEncounterActivity extends Activity { - private WorldContext world; - - @Override + + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - this.world = app.world; + final WorldContext world = app.getWorld(); + final ViewContext view = app.getViewContext(); requestWindowFeature(Window.FEATURE_NO_TITLE); @@ -34,7 +35,7 @@ public final class MonsterEncounterActivity extends Activity { setContentView(R.layout.monsterencounter); - CharSequence difficulty = getText(MonsterInfoActivity.getMonsterDifficultyResource(world, monster)); + CharSequence difficulty = getText(MonsterInfoActivity.getMonsterDifficultyResource(view, monster)); TextView tv = (TextView) findViewById(R.id.monsterencounter_title); tv.setText(monster.getName()); @@ -50,7 +51,7 @@ public final class MonsterEncounterActivity extends Activity { setResult(RESULT_OK); MonsterEncounterActivity.this.finish(); } - }); + }); b = (Button) findViewById(R.id.monsterencounter_cancel); b.setOnClickListener(new OnClickListener() { @Override @@ -58,13 +59,13 @@ public final class MonsterEncounterActivity extends Activity { setResult(RESULT_CANCELED); MonsterEncounterActivity.this.finish(); } - }); + }); b = (Button) findViewById(R.id.monsterencounter_info); b.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { Dialogs.showMonsterInfo(MonsterEncounterActivity.this, monster); } - }); + }); } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterInfoActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterInfoActivity.java index 21069760b..a82d74a7f 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterInfoActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterInfoActivity.java @@ -1,27 +1,27 @@ package com.gpl.rpg.AndorsTrail.activity; +import android.app.Activity; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.Button; +import android.widget.TextView; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.Dialogs; 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.CombatController; import com.gpl.rpg.AndorsTrail.model.actor.Monster; import com.gpl.rpg.AndorsTrail.view.ItemEffectsView; import com.gpl.rpg.AndorsTrail.view.RangeBar; 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; -import android.widget.TextView; - public final class MonsterInfoActivity extends Activity { private WorldContext world; + private ViewContext view; private TextView monsterinfo_title; private TextView monsterinfo_difficulty; @@ -36,7 +36,8 @@ public final class MonsterInfoActivity extends Activity { super.onCreate(savedInstanceState); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - this.world = app.world; + this.world = app.getWorld(); + this.view = app.getViewContext(); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.monsterinfo); @@ -76,7 +77,7 @@ public final class MonsterInfoActivity extends Activity { private void updateTitle(Monster monster) { monsterinfo_title.setText(monster.getName()); world.tileManager.setImageViewTile(monsterinfo_title, monster); - monsterinfo_difficulty.setText(getMonsterDifficultyResource(world, monster)); + monsterinfo_difficulty.setText(getMonsterDifficultyResource(view, monster)); } private void updateTraits(Monster monster) { @@ -87,17 +88,17 @@ public final class MonsterInfoActivity extends Activity { monster.getOnHitEffectsAsList(), null, false); - hp.update(monster.health); - monsterinfo_max_ap.setText(Integer.toString(monster.ap.max)); + hp.update(monster.getMaxHP(), monster.getCurrentHP()); + monsterinfo_max_ap.setText(Integer.toString(monster.getMaxAP())); } - public static int getMonsterDifficultyResource(WorldContext world, Monster monster) { - final int difficulty = CombatController.getMonsterDifficulty(world, monster); + public static int getMonsterDifficultyResource(ViewContext viewContext, Monster monster) { + final int difficulty = viewContext.combatController.getMonsterDifficulty(monster); if (difficulty >= 80) return R.string.monster_difficulty_veryeasy; - else if (difficulty >= 60) return R.string.monster_difficulty_easy; - else if (difficulty >= 40) return R.string.monster_difficulty_normal; - else if (difficulty >= 20) return R.string.monster_difficulty_hard; - else if (difficulty == 0) return R.string.monster_difficulty_impossible; - else return R.string.monster_difficulty_veryhard; + if (difficulty >= 60) return R.string.monster_difficulty_easy; + if (difficulty >= 40) return R.string.monster_difficulty_normal; + if (difficulty >= 20) return R.string.monster_difficulty_hard; + if (difficulty == 0) return R.string.monster_difficulty_impossible; + return R.string.monster_difficulty_veryhard; } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ShopActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ShopActivity.java index 033dca1a8..330d3a968 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ShopActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ShopActivity.java @@ -29,8 +29,6 @@ public final class ShopActivity extends TabActivity implements OnContainerItemCl private WorldContext world; private Player player; - private ListView shoplist_buy; - private ListView shoplist_sell; private ItemContainer container_buy; private TextView shop_buy_gc; private TextView shop_sell_gc; @@ -43,14 +41,13 @@ public final class ShopActivity extends TabActivity implements OnContainerItemCl AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - this.world = app.world; + this.world = app.getWorld(); this.player = world.model.player; - AndorsTrailApplication.setWindowParameters(this, app.preferences); + app.setWindowParameters(this); final Monster npc = Dialogs.getMonsterFromIntent(getIntent(), world); - final Player player = world.model.player; - + setContentView(R.layout.shop); final Resources res = getResources(); @@ -65,9 +62,9 @@ public final class ShopActivity extends TabActivity implements OnContainerItemCl h.setup(); shop_buy_gc = (TextView) h.findViewById(R.id.shop_buy_gc); shop_sell_gc = (TextView) h.findViewById(R.id.shop_sell_gc); - - shoplist_buy = (ListView) h.findViewById(R.id.shop_buy_list); - shoplist_sell = (ListView) h.findViewById(R.id.shop_sell_list); + + ListView shoplist_buy = (ListView) h.findViewById(R.id.shop_buy_list); + ListView shoplist_sell = (ListView) h.findViewById(R.id.shop_sell_list); container_buy = npc.getShopItems(player); @@ -95,7 +92,7 @@ public final class ShopActivity extends TabActivity implements OnContainerItemCl public void onItemInfoClicked(int position, ItemType itemType, boolean isSelling) { int price; int resid; - boolean enableButton = true; + boolean enableButton; int action; if (isSelling) { resid = R.string.shop_sellitem; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/SkillInfoActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/SkillInfoActivity.java index a4861bbb1..1811967de 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/SkillInfoActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/SkillInfoActivity.java @@ -21,18 +21,16 @@ import android.widget.Button; import android.widget.TextView; public final class SkillInfoActivity extends Activity { - private WorldContext world; - private Player player; - + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); if (!app.isInitialized()) { finish(); return; } - this.world = app.world; - this.player = world.model.player; + final WorldContext world = app.getWorld(); + final Player player = world.model.player; - AndorsTrailApplication.setWindowParameters(this, app.preferences); + app.setWindowParameters(this); setContentView(R.layout.skill_info_view); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/StartScreenActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/StartScreenActivity.java index be52021ad..14f94e69f 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/StartScreenActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/StartScreenActivity.java @@ -4,10 +4,11 @@ import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences; import com.gpl.rpg.AndorsTrail.Dialogs; import com.gpl.rpg.AndorsTrail.R; -import com.gpl.rpg.AndorsTrail.Savegames; +import com.gpl.rpg.AndorsTrail.savegames.Savegames; import com.gpl.rpg.AndorsTrail.WorldSetup; -import com.gpl.rpg.AndorsTrail.Savegames.FileHeader; +import com.gpl.rpg.AndorsTrail.savegames.Savegames.FileHeader; import com.gpl.rpg.AndorsTrail.controller.Constants; +import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager; import android.app.Activity; import android.app.AlertDialog; @@ -39,14 +40,15 @@ public final class StartScreenActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); - AndorsTrailPreferences.read(this, app.preferences); - AndorsTrailApplication.setWindowParameters(this, app.preferences); + final AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivity(this); + final AndorsTrailPreferences preferences = app.getPreferences(); + AndorsTrailPreferences.read(this, preferences); + app.setWindowParameters(this); setContentView(R.layout.startscreen); TextView tv = (TextView) findViewById(R.id.startscreen_version); - tv.setText("v" + AndorsTrailApplication.CURRENT_VERSION_DISPLAY); + tv.setText('v' + AndorsTrailApplication.CURRENT_VERSION_DISPLAY); startscreen_currenthero = (TextView) findViewById(R.id.startscreen_currenthero); startscreen_enterheroname = (EditText) findViewById(R.id.startscreen_enterheroname); @@ -103,9 +105,10 @@ public final class StartScreenActivity extends Activity { } final Resources res = getResources(); - app.world.tileManager.setDensity(res); - app.world.tileManager.updatePreferences(app.preferences); - app.setup.startResourceLoader(res, app.preferences); + TileManager tileManager = app.getWorld().tileManager; + tileManager.setDensity(res); + tileManager.updatePreferences(preferences); + app.getWorldSetup().startResourceLoader(res); if (AndorsTrailApplication.DEVELOPMENT_FORCE_STARTNEWGAME) { if (AndorsTrailApplication.DEVELOPMENT_DEBUGRESOURCES) { @@ -123,7 +126,7 @@ public final class StartScreenActivity extends Activity { protected void onResume() { super.onResume(); - String playerName = null; + String playerName; String displayInfo = null; FileHeader header = Savegames.quickload(this, Savegames.SLOT_QUICKSAVE); @@ -187,7 +190,7 @@ public final class StartScreenActivity extends Activity { } private void continueGame(boolean createNewCharacter, int loadFromSlot, String name) { - final WorldSetup setup = AndorsTrailApplication.getApplicationFromActivity(this).setup; + final WorldSetup setup = AndorsTrailApplication.getApplicationFromActivity(this).getWorldSetup(); setup.createNewCharacter = createNewCharacter; setup.loadFromSlot = loadFromSlot; setup.newHeroName = name; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/context/ViewContext.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/context/ViewContext.java index 7e1759b0a..5233d506f 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/context/ViewContext.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/context/ViewContext.java @@ -1,49 +1,61 @@ package com.gpl.rpg.AndorsTrail.context; +import java.lang.ref.WeakReference; + +import android.content.res.Resources; + import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences; -import com.gpl.rpg.AndorsTrail.activity.MainActivity; import com.gpl.rpg.AndorsTrail.controller.ActorStatsController; import com.gpl.rpg.AndorsTrail.controller.CombatController; import com.gpl.rpg.AndorsTrail.controller.Controller; +import com.gpl.rpg.AndorsTrail.controller.ConversationController; import com.gpl.rpg.AndorsTrail.controller.GameRoundController; +import com.gpl.rpg.AndorsTrail.controller.MonsterSpawningController; +import com.gpl.rpg.AndorsTrail.controller.SkillController; import com.gpl.rpg.AndorsTrail.controller.VisualEffectController; import com.gpl.rpg.AndorsTrail.controller.ItemController; import com.gpl.rpg.AndorsTrail.controller.MonsterMovementController; import com.gpl.rpg.AndorsTrail.controller.MovementController; import com.gpl.rpg.AndorsTrail.controller.InputController; -public class ViewContext extends WorldContext { - //Views - public final MainActivity mainActivity; - +public final class ViewContext { //Controllers public final Controller controller; public final GameRoundController gameRoundController; public final CombatController combatController; + public final ConversationController conversationController; public final VisualEffectController effectController; public final ItemController itemController; public final MonsterMovementController monsterMovementController; + public final MonsterSpawningController monsterSpawnController; public final MovementController movementController; public final ActorStatsController actorStatsController; public final InputController inputController; + public final SkillController skillController; public final AndorsTrailPreferences preferences; - + public final WeakReference app; - public ViewContext(AndorsTrailApplication application, MainActivity mainActivity) { - super(application.world); - this.mainActivity = mainActivity; - this.preferences = application.preferences; + public ViewContext(AndorsTrailApplication app, WorldContext world) { + this.app = new WeakReference(app); + this.preferences = app.getPreferences(); - this.controller = new Controller(this); - this.gameRoundController = new GameRoundController(this); - this.combatController = new CombatController(this); - this.effectController = new VisualEffectController(this); - this.itemController = new ItemController(this); - this.monsterMovementController = new MonsterMovementController(this); - this.movementController = new MovementController(this); - this.actorStatsController = new ActorStatsController(this); - this.inputController = new InputController(this); + this.controller = new Controller(this, world); + this.gameRoundController = new GameRoundController(this, world); + this.combatController = new CombatController(this, world); + this.conversationController = new ConversationController(this, world); + this.effectController = new VisualEffectController(this, world); + this.itemController = new ItemController(this, world); + this.monsterMovementController = new MonsterMovementController(this, world); + this.monsterSpawnController = new MonsterSpawningController(this, world); + this.movementController = new MovementController(this, world); + this.actorStatsController = new ActorStatsController(this, world); + this.inputController = new InputController(this, world); + this.skillController = new SkillController(this, world); + } + + public Resources getResources() { + return app.get().getResources(); } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/context/WorldContext.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/context/WorldContext.java index ce7aacc03..3885da1c4 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/context/WorldContext.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/context/WorldContext.java @@ -13,7 +13,7 @@ import com.gpl.rpg.AndorsTrail.model.map.MapCollection; import com.gpl.rpg.AndorsTrail.model.quest.QuestCollection; import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager; -public class WorldContext { +public final class WorldContext { //Objectcollections public final ConversationLoader conversationLoader; public final ItemTypeCollection itemTypes; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ActorStatsController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ActorStatsController.java index 007b5c5b3..912be56a1 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ActorStatsController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ActorStatsController.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import com.gpl.rpg.AndorsTrail.VisualEffectCollection; import com.gpl.rpg.AndorsTrail.context.ViewContext; +import com.gpl.rpg.AndorsTrail.context.WorldContext; +import com.gpl.rpg.AndorsTrail.model.listeners.PlayerStatsListeners; import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition; import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionEffect; import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionType; @@ -17,19 +19,24 @@ import com.gpl.rpg.AndorsTrail.model.item.Inventory; import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnEquip; import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnUse; import com.gpl.rpg.AndorsTrail.model.item.ItemType; +import com.gpl.rpg.AndorsTrail.model.listeners.ActorConditionListeners; +import com.gpl.rpg.AndorsTrail.model.listeners.ActorStatsListeners; import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; import com.gpl.rpg.AndorsTrail.model.map.MonsterSpawnArea; -public class ActorStatsController { +public final class ActorStatsController { private final ViewContext view; - //private final WorldContext world; + private final WorldContext world; + public final ActorConditionListeners actorConditionListeners = new ActorConditionListeners(); + public final ActorStatsListeners actorStatsListeners = new ActorStatsListeners(); + public final PlayerStatsListeners playerStatsListeners = new PlayerStatsListeners(); - public ActorStatsController(ViewContext context) { + public ActorStatsController(ViewContext context, WorldContext world) { this.view = context; - //this.world = context; + this.world = world; } - public static void addConditionsFromEquippedItem(Player player, ItemType itemType) { + public void addConditionsFromEquippedItem(Player player, ItemType itemType) { ItemTraits_OnEquip equipEffects = itemType.effects_equip; if (equipEffects == null) return; if (equipEffects.addedConditions == null) return; @@ -37,7 +44,7 @@ public class ActorStatsController { applyActorCondition(player, e, ActorCondition.DURATION_FOREVER); } } - public static void removeConditionsFromUnequippedItem(Player player, ItemType itemType) { + public void removeConditionsFromUnequippedItem(Player player, ItemType itemType) { ItemTraits_OnEquip equipEffects = itemType.effects_equip; if (equipEffects == null) return; if (equipEffects.addedConditions == null) return; @@ -52,7 +59,7 @@ public class ActorStatsController { } } - private static void removeStackableActorCondition(Actor actor, ActorConditionType type, int magnitude, int duration) { + private void removeStackableActorCondition(Actor actor, ActorConditionType type, int magnitude, int duration) { for(int i = actor.conditions.size() - 1; i >= 0; --i) { ActorCondition c = actor.conditions.get(i); if (!type.conditionTypeID.equals(c.conditionType.conditionTypeID)) continue; @@ -60,16 +67,16 @@ public class ActorStatsController { if (c.magnitude > magnitude) { c.magnitude -= magnitude; - actor.conditionListener.onActorConditionMagnitudeChanged(actor, c); + actorConditionListeners.onActorConditionMagnitudeChanged(actor, c); } else { actor.conditions.remove(i); - actor.conditionListener.onActorConditionRemoved(actor, c); + actorConditionListeners.onActorConditionRemoved(actor, c); } break; } } - private static void removeNonStackableActorCondition(Player player, ActorConditionType type, int magnitude, int duration) { + private void removeNonStackableActorCondition(Player player, ActorConditionType type, int magnitude, int duration) { for (int i = 0; i < Inventory.NUM_WORN_SLOTS; ++i) { ItemType t = player.inventory.wear[i]; if (t == null) continue; @@ -87,8 +94,8 @@ public class ActorStatsController { removeStackableActorCondition(player, type, magnitude, duration); } - public static void applyActorCondition(Actor actor, ActorConditionEffect e) { applyActorCondition(actor, e, e.duration); } - private static void applyActorCondition(Actor actor, ActorConditionEffect e, int duration) { + public void applyActorCondition(Actor actor, ActorConditionEffect e) { applyActorCondition(actor, e, e.duration); } + private void applyActorCondition(Actor actor, ActorConditionEffect e, int duration) { if (e.isRemovalEffect()) { removeAllConditionsOfType(actor, e.conditionType.conditionTypeID); } else if (e.magnitude > 0) { @@ -101,7 +108,7 @@ public class ActorStatsController { recalculateActorCombatTraits(actor); } - private static void addStackableActorCondition(Actor actor, ActorConditionEffect e, int duration) { + private void addStackableActorCondition(Actor actor, ActorConditionEffect e, int duration) { final ActorConditionType type = e.conditionType; int magnitude = e.magnitude; @@ -111,66 +118,66 @@ public class ActorStatsController { if (c.duration == duration) { // If the actor already has a condition of this type and the same duration, just increase the magnitude instead. c.magnitude += magnitude; - actor.conditionListener.onActorConditionMagnitudeChanged(actor, c); + actorConditionListeners.onActorConditionMagnitudeChanged(actor, c); return; } } ActorCondition c = new ActorCondition(type, magnitude, duration); actor.conditions.add(c); - actor.conditionListener.onActorConditionAdded(actor, c); + actorConditionListeners.onActorConditionAdded(actor, c); } - private static void addNonStackableActorCondition(Actor actor, ActorConditionEffect e, int duration) { + private void addNonStackableActorCondition(Actor actor, ActorConditionEffect e, int duration) { final ActorConditionType type = e.conditionType; for(int i = actor.conditions.size() - 1; i >= 0; --i) { 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.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); + actorConditionListeners.onActorConditionRemoved(actor, c); } ActorCondition c = e.createCondition(duration); actor.conditions.add(c); - actor.conditionListener.onActorConditionAdded(actor, c); + actorConditionListeners.onActorConditionAdded(actor, c); } - public static void removeAllTemporaryConditions(final Actor actor) { + public void removeAllTemporaryConditions(final Actor actor) { for(int i = actor.conditions.size() - 1; i >= 0; --i) { ActorCondition c = actor.conditions.get(i); if (!c.isTemporaryEffect()) continue; actor.conditions.remove(i); - actor.conditionListener.onActorConditionRemoved(actor, c); + actorConditionListeners.onActorConditionRemoved(actor, c); } } - private static void removeAllConditionsOfType(final Actor actor, final String conditionTypeID) { + private void removeAllConditionsOfType(final Actor actor, final String conditionTypeID) { for(int i = actor.conditions.size() - 1; i >= 0; --i) { ActorCondition c = actor.conditions.get(i); if (!c.conditionType.conditionTypeID.equals(conditionTypeID)) continue; actor.conditions.remove(i); - actor.conditionListener.onActorConditionRemoved(actor, c); + actorConditionListeners.onActorConditionRemoved(actor, c); } } - private static void applyEffectsFromCurrentConditions(Actor actor) { + private void applyEffectsFromCurrentConditions(Actor actor) { for (ActorCondition c : actor.conditions) { applyAbilityEffects(actor, c.conditionType.abilityEffect, c.magnitude); } } - public static void applyAbilityEffects(Actor actor, AbilityModifierTraits effects, int multiplier) { + public void applyAbilityEffects(Actor actor, AbilityModifierTraits effects, int multiplier) { if (effects == null) return; - actor.health.addToMax(effects.increaseMaxHP * multiplier); - actor.ap.addToMax(effects.increaseMaxAP * multiplier); - actor.moveCost += effects.increaseMoveCost * multiplier; + addActorMaxHealth(actor, effects.increaseMaxHP * multiplier, false); + addActorMaxAP(actor, effects.increaseMaxAP * multiplier, false); - actor.attackCost += effects.increaseAttackCost * multiplier; + addActorMoveCost(actor, effects.increaseMoveCost * multiplier); + addActorAttackCost(actor, effects.increaseAttackCost * multiplier); //criticalMultiplier should not be increased. It is always defined by the weapon in use. actor.attackChance += effects.increaseAttackChance * multiplier; actor.criticalSkill += effects.increaseCriticalSkill * multiplier; @@ -179,29 +186,27 @@ public class ActorStatsController { actor.blockChance += effects.increaseBlockChance * multiplier; actor.damageResistance += effects.increaseDamageResistance * multiplier; - 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 recalculatePlayerStats(Player player) { + public void recalculatePlayerStats(Player player) { player.resetStatsToBaseTraits(); player.recalculateLevelExperience(); - ItemController.applyInventoryEffects(player); - SkillController.applySkillEffects(player); + view.itemController.applyInventoryEffects(player); + view.skillController.applySkillEffects(player); applyEffectsFromCurrentConditions(player); ItemController.recalculateHitEffectsFromWornItems(player); - player.health.capAtMax(); - player.ap.capAtMax(); + capActorHealthAtMax(player); + capActorAPAtMax(player); } - public static void recalculateMonsterCombatTraits(Monster monster) { + public void recalculateMonsterCombatTraits(Monster monster) { monster.resetStatsToBaseTraits(); applyEffectsFromCurrentConditions(monster); - monster.health.capAtMax(); - monster.ap.capAtMax(); + capActorHealthAtMax(monster); + capActorAPAtMax(monster); } - private static void recalculateActorCombatTraits(Actor actor) { + private void recalculateActorCombatTraits(Actor actor) { if (actor.isPlayer) recalculatePlayerStats((Player) actor); else recalculateMonsterCombatTraits((Monster) actor); } @@ -217,21 +222,19 @@ public class ActorStatsController { } if (!isFullRound) decreaseDurationAndRemoveConditions(player); - - view.mainActivity.updateStatus(); } - private static void removeConditionsFromSkillEffects(Player player) { + private void removeConditionsFromSkillEffects(Player player) { if (SkillController.rollForSkillChance(player, SkillCollection.SKILL_REJUVENATION, SkillCollection.PER_SKILLPOINT_INCREASE_REJUVENATION_CHANCE)) { int i = getRandomConditionForRejuvenate(player); if (i >= 0) { ActorCondition c = player.conditions.get(i); if (c.magnitude > 1) { c.magnitude -= 1; - player.conditionListener.onActorConditionMagnitudeChanged(player, c); + actorConditionListeners.onActorConditionMagnitudeChanged(player, c); } else { player.conditions.remove(i); - player.conditionListener.onActorConditionRemoved(player, c); + actorConditionListeners.onActorConditionRemoved(player, c); } recalculatePlayerStats(player); } @@ -278,23 +281,23 @@ 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); + if (effect != null) actorConditionListeners.onActorConditionRoundEffectApplied(actor, c); } startVisualEffect(actor, effectToStart); } - private static void decreaseDurationAndRemoveConditions(Actor actor) { + private void decreaseDurationAndRemoveConditions(Actor actor) { boolean removedAnyConditions = false; for(int i = actor.conditions.size() - 1; i >= 0; --i) { ActorCondition c = actor.conditions.get(i); if (!c.isTemporaryEffect()) continue; if (c.duration <= 1) { actor.conditions.remove(i); - actor.conditionListener.onActorConditionRemoved(actor, c); + actorConditionListeners.onActorConditionRemoved(actor, c); removedAnyConditions = true; } else { c.duration -= 1; - actor.conditionListener.onActorConditionDurationChanged(actor, c); + actorConditionListeners.onActorConditionDurationChanged(actor, c); } } if (removedAnyConditions) { @@ -323,7 +326,7 @@ public class ActorStatsController { } } - private static void rollForConditionEffect(Actor actor, ActorConditionEffect conditionEffect) { + private void rollForConditionEffect(Actor actor, ActorConditionEffect conditionEffect) { int chanceRollBias = 0; if (actor.isPlayer) chanceRollBias = SkillController.getActorConditionEffectChanceRollBias(conditionEffect, (Player) actor); @@ -342,15 +345,14 @@ public class ActorStatsController { private void startVisualEffect(Actor actor, VisualEffect effectToStart) { if (effectToStart == null) return; view.effectController.startEffect( - view.mainActivity.mainview - , actor.position + actor.position , effectToStart.visualEffectID , effectToStart.effectValue , null , 0); } - private static VisualEffect applyStatsModifierEffect(Actor actor, StatsModifierTraits effect, int magnitude, VisualEffect existingVisualEffect) { + private VisualEffect applyStatsModifierEffect(Actor actor, StatsModifierTraits effect, int magnitude, VisualEffect existingVisualEffect) { if (effect == null) return existingVisualEffect; int effectValue = 0; @@ -358,7 +360,7 @@ public class ActorStatsController { if (effect.currentAPBoost != null) { effectValue = Constants.rollValue(effect.currentAPBoost); effectValue *= magnitude; - boolean changed = actor.ap.change(effectValue, false, false); + boolean changed = changeActorAP(actor, effectValue, false, false); if (!changed) effectValue = 0; // So that the visualeffect doesn't start. if (effectValue != 0) { if (!effect.hasVisualEffect()) { @@ -369,7 +371,7 @@ public class ActorStatsController { if (effect.currentHPBoost != null) { effectValue = Constants.rollValue(effect.currentHPBoost); effectValue *= magnitude; - boolean changed = actor.health.change(effectValue, false, false); + boolean changed = changeActorHealth(actor, effectValue, false, false); if (!changed) effectValue = 0; // So that the visualeffect doesn't start. if (effectValue != 0) { if (!effect.hasVisualEffect()) { @@ -406,9 +408,123 @@ public class ActorStatsController { if (level > 0) { 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(); + addActorHealth(player, level * SkillCollection.PER_SKILLPOINT_INCREASE_REGENERATION); } } } + + public static final int LEVELUP_HEALTH = 0; + public static final int LEVELUP_ATTACK_CHANCE = 1; + public static final int LEVELUP_ATTACK_DAMAGE = 2; + public static final int LEVELUP_BLOCK_CHANCE = 3; + + public void addLevelupEffect(Player player, int selectionID) { + int hpIncrease = 0; + switch (selectionID) { + case LEVELUP_HEALTH: + hpIncrease = Constants.LEVELUP_EFFECT_HEALTH; + break; + case LEVELUP_ATTACK_CHANCE: + player.baseTraits.attackChance += Constants.LEVELUP_EFFECT_ATK_CH; + break; + case LEVELUP_ATTACK_DAMAGE: + player.baseTraits.damagePotential.max += Constants.LEVELUP_EFFECT_ATK_DMG; + player.baseTraits.damagePotential.current += Constants.LEVELUP_EFFECT_ATK_DMG; + break; + case LEVELUP_BLOCK_CHANCE: + player.baseTraits.blockChance += Constants.LEVELUP_EFFECT_DEF_CH; + break; + } + if (player.nextLevelAddsNewSkillpoint()) { + player.availableSkillIncreases++; + } + player.level++; + + hpIncrease += player.getSkillLevel(SkillCollection.SKILL_FORTITUDE) * SkillCollection.PER_SKILLPOINT_INCREASE_FORTITUDE_HEALTH; + addActorMaxHealth(player, hpIncrease, true); + player.baseTraits.maxHP += hpIncrease; + + recalculatePlayerStats(player); + } + + public void healAllMonsters(MonsterSpawnArea area) { + for (Monster m : area.monsters) { + removeAllTemporaryConditions(m); + setActorMaxHealth(m); + } + } + + public void addExperience(int exp) { + if (exp == 0) return; + Player p = world.model.player; + p.totalExperience += exp; + p.levelExperience.add(exp, true); + playerStatsListeners.onPlayerExperienceChanged(p); + } + public void addActorMoveCost(Actor actor, int amount) { + if (amount == 0) return; + actor.moveCost += amount; + if (actor.moveCost <= 0) actor.moveCost = 1; + actorStatsListeners.onActorMoveCostChanged(actor, actor.moveCost); + } + public void addActorAttackCost(Actor actor, int amount) { + if (amount == 0) return; + actor.attackCost += amount; + if (actor.attackCost <= 0) actor.attackCost = 1; + actorStatsListeners.onActorAttackCostChanged(actor, actor.attackCost); + } + + public void setActorMaxHealth(Actor actor) { + if (actor.health.isMax()) return; + actor.health.setMax(); + actorStatsListeners.onActorHealthChanged(actor); + } + public void capActorHealthAtMax(Actor actor) { + if (actor.health.capAtMax()) actorStatsListeners.onActorHealthChanged(actor); + } + public boolean addActorHealth(Actor actor, int amount) { return changeActorHealth(actor, amount, false, false); } + public boolean removeActorHealth(Actor actor, int amount) { return changeActorHealth(actor, -amount, false, false); } + public boolean changeActorHealth(Actor actor, int deltaAmount, boolean mayUnderflow, boolean mayOverflow) { + final boolean changed = actor.health.change(deltaAmount, mayUnderflow, mayOverflow); + if(changed) actorStatsListeners.onActorHealthChanged(actor); + return changed; + } + public void addActorMaxHealth(Actor actor, int amount, boolean affectCurrentHealth) { + if (amount == 0) return; + actor.health.addToMax(amount); + if (affectCurrentHealth) actor.health.add(amount, false); + actorStatsListeners.onActorHealthChanged(actor); + } + + public void setActorMaxAP(Actor actor) { + if (actor.ap.isMax()) return; + actor.ap.setMax(); + actorStatsListeners.onActorAPChanged(actor); + } + public void capActorAPAtMax(Actor actor) { + if (actor.ap.capAtMax()) actorStatsListeners.onActorAPChanged(actor); + } + public boolean addActorAP(Actor actor, int amount) { return changeActorAP(actor, amount, false, false); } + public boolean changeActorAP(Actor actor, int deltaAmount, boolean mayUnderflow, boolean mayOverflow) { + final boolean changed = actor.ap.change(deltaAmount, mayUnderflow, mayOverflow); + if(changed) actorStatsListeners.onActorAPChanged(actor); + return changed; + } + public boolean useAPs(Actor actor, int cost) { + if (actor.ap.current < cost) return false; + actor.ap.subtract(cost, false); + actorStatsListeners.onActorAPChanged(actor); + return true; + } + public void addActorMaxAP(Actor actor, int amount, boolean affectCurrentAP) { + if (amount == 0) return; + actor.ap.addToMax(amount); + if (affectCurrentAP) actor.ap.add(amount, false); + actorStatsListeners.onActorAPChanged(actor); + } + public void setActorMinAP(Actor actor) { + if (actor.ap.current == 0) return; + actor.ap.current = 0; + actorStatsListeners.onActorAPChanged(actor); + } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/CombatController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/CombatController.java index 163b3ae60..d9ae71695 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/CombatController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/CombatController.java @@ -1,21 +1,20 @@ package com.gpl.rpg.AndorsTrail.controller; -import java.util.HashSet; +import java.util.ArrayList; -import android.content.res.Resources; import android.os.Handler; import android.os.Message; import android.util.FloatMath; import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences; -import com.gpl.rpg.AndorsTrail.Dialogs; import com.gpl.rpg.AndorsTrail.VisualEffectCollection; -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.VisualEffectController.VisualEffectCompletedCallback; +import com.gpl.rpg.AndorsTrail.controller.listeners.CombatActionListeners; +import com.gpl.rpg.AndorsTrail.controller.listeners.CombatSelectionListeners; +import com.gpl.rpg.AndorsTrail.controller.listeners.CombatTurnListeners; import com.gpl.rpg.AndorsTrail.model.AttackResult; -import com.gpl.rpg.AndorsTrail.model.ModelContainer; import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection; import com.gpl.rpg.AndorsTrail.model.actor.Actor; import com.gpl.rpg.AndorsTrail.model.actor.Monster; @@ -25,21 +24,21 @@ import com.gpl.rpg.AndorsTrail.model.item.Loot; import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; import com.gpl.rpg.AndorsTrail.model.map.MonsterSpawnArea; import com.gpl.rpg.AndorsTrail.util.Coord; -import com.gpl.rpg.AndorsTrail.view.MainView; public final class CombatController implements VisualEffectCompletedCallback { - private final ViewContext context; + private final ViewContext view; private final WorldContext world; - private final ModelContainer model; + public final CombatSelectionListeners combatSelectionListeners = new CombatSelectionListeners(); + public final CombatActionListeners combatActionListeners = new CombatActionListeners(); + public final CombatTurnListeners combatTurnListeners = new CombatTurnListeners(); private Monster currentActiveMonster = null; - private final HashSet killedMonsterBags = new HashSet(); + private final ArrayList killedMonsterBags = new ArrayList(); private int totalExpThisFight = 0; - public CombatController(ViewContext context) { - this.context = context; - this.world = context; - this.model = world.model; + public CombatController(ViewContext view, WorldContext world) { + this.view = view; + this.world = world; } public static final int BEGIN_TURN_PLAYER = 0; @@ -47,70 +46,66 @@ public final class CombatController implements VisualEffectCompletedCallback { public static final int BEGIN_TURN_CONTINUE = 2; public void enterCombat(int beginTurnAs) { - context.mainActivity.combatview.show(); - model.uiSelections.isInCombat = true; + world.model.uiSelections.isInCombat = true; killedMonsterBags.clear(); - context.mainActivity.clearMessages(); + combatTurnListeners.onCombatStarted(); if (beginTurnAs == BEGIN_TURN_PLAYER) newPlayerTurn(true); else if (beginTurnAs == BEGIN_TURN_MONSTERS) beginMonsterTurn(true); else continueTurn(); - updateTurnInfo(); } public void exitCombat(boolean pickupLootBags) { setCombatSelection(null, null); - context.mainActivity.combatview.hide(); - model.uiSelections.isInCombat = false; - context.mainActivity.clearMessages(); + world.model.uiSelections.isInCombat = false; + combatTurnListeners.onCombatEnded(); currentActiveMonster = null; - model.uiSelections.selectedPosition = null; - model.uiSelections.selectedMonster = null; - if (!killedMonsterBags.isEmpty()) { + world.model.uiSelections.selectedPosition = null; + world.model.uiSelections.selectedMonster = null; + if (killedMonsterBags.isEmpty()) { + view.gameRoundController.resume(); + } else { if (pickupLootBags) { - lootCurrentMonsterBags(); + view.itemController.lootMonsterBags(killedMonsterBags, totalExpThisFight); } killedMonsterBags.clear(); - } else { - context.gameRoundController.resume(); } totalExpThisFight = 0; } - private void lootCurrentMonsterBags() { - Dialogs.showMonsterLoot(context.mainActivity, context, killedMonsterBags, totalExpThisFight); - ItemController.consumeNonItemLoot(killedMonsterBags, model); - } - public boolean isMonsterTurn() { return currentActiveMonster != null; } public void setCombatSelection(Monster selectedMonster) { - Coord p = selectedMonster.rectPosition.findPositionAdjacentTo(model.player.position); + Coord p = selectedMonster.rectPosition.findPositionAdjacentTo(world.model.player.position); setCombatSelection(selectedMonster, p); } public void setCombatSelection(Monster selectedMonster, Coord selectedPosition) { if (selectedMonster != null) { if (!selectedMonster.isAgressive()) return; } - Coord previousSelection = model.uiSelections.selectedPosition; - if (model.uiSelections.selectedPosition != null) { - model.uiSelections.selectedPosition = null; + Coord previousSelection = world.model.uiSelections.selectedPosition; + if (previousSelection != null) { + world.model.uiSelections.selectedPosition = null; if (selectedPosition == null || !selectedPosition.equals(previousSelection)) { - context.mainActivity.redrawTile(previousSelection, MainView.REDRAW_TILE_SELECTION_REMOVED); + } else { + previousSelection = null; } } - context.mainActivity.combatview.updateCombatSelection(selectedMonster, selectedPosition); - model.uiSelections.selectedMonster = selectedMonster; + world.model.uiSelections.selectedMonster = selectedMonster; if (selectedPosition != null) { - model.uiSelections.selectedPosition = new Coord(selectedPosition); - model.uiSelections.isInCombat = true; - context.mainActivity.redrawTile(selectedPosition, MainView.REDRAW_TILE_SELECTION_ADDED); + world.model.uiSelections.selectedPosition = new Coord(selectedPosition); + world.model.uiSelections.isInCombat = true; } else { - model.uiSelections.selectedPosition = null; + world.model.uiSelections.selectedPosition = null; } + + if (selectedMonster != null) combatSelectionListeners.onMonsterSelected(selectedMonster, selectedPosition, previousSelection); + else if (selectedPosition != null) combatSelectionListeners.onMovementDestinationSelected(selectedPosition, previousSelection); + else if (previousSelection != null) combatSelectionListeners.onCombatSelectionCleared(previousSelection); } + public void setCombatSelection(Coord p) { - PredefinedMap map = model.currentMap; + PredefinedMap map = world.model.currentMap; Monster m = map.getMonsterAt(p); if (m != null) { setCombatSelection(m, p); @@ -119,27 +114,24 @@ public final class CombatController implements VisualEffectCompletedCallback { } } - private void message(String s) { - context.mainActivity.message(s); - } private boolean useAPs(int cost) { - if (model.player.useAPs(cost)) { + if (view.actorStatsController.useAPs(world.model.player, cost)) { return true; } else { - message(context.mainActivity.getResources().getString(R.string.combat_not_enough_ap)); + combatActionListeners.onPlayerDoesNotHaveEnoughAP(); return false; } } public boolean canExitCombat() { return getAdjacentMonster() == null; } private Monster getAdjacentMonster() { - return MovementController.getAdjacentAggressiveMonster(model.currentMap, model.player); + return MovementController.getAdjacentAggressiveMonster(world.model.currentMap, world.model.player); } public void executeMoveAttack(int dx, int dy) { - if (isMonsterTurn()) { - return; - } else if (world.model.uiSelections.selectedMonster != null) { + if (isMonsterTurn()) return; + + if (world.model.uiSelections.selectedMonster != null) { executePlayerAttack(); } else if (world.model.uiSelections.selectedPosition != null) { executeCombatMove(world.model.uiSelections.selectedPosition); @@ -157,46 +149,31 @@ public final class CombatController implements VisualEffectCompletedCallback { private void executeFlee(int dx, int dy) { // avoid monster fields when fleeing - if (!context.movementController.findWalkablePosition(dx, dy, AndorsTrailPreferences.MOVEMENTAGGRESSIVENESS_DEFENSIVE)) return; - Monster m = model.currentMap.getMonsterAt(model.player.nextPosition); + if (!view.movementController.findWalkablePosition(dx, dy, AndorsTrailPreferences.MOVEMENTAGGRESSIVENESS_DEFENSIVE)) return; + Monster m = world.model.currentMap.getMonsterAt(world.model.player.nextPosition); if (m != null) return; executeCombatMove(world.model.player.nextPosition); } - - private Monster currentlyAttackedMonster; + private AttackResult lastAttackResult; private void executePlayerAttack() { - if (context.effectController.isRunningVisualEffect()) return; - if (!useAPs(model.player.getAttackCost())) return; - final Monster target = model.uiSelections.selectedMonster; - this.currentlyAttackedMonster = target; - - final AttackResult attack = playerAttacks(world, target); + if (view.effectController.isRunningVisualEffect()) return; + if (!useAPs(world.model.player.getAttackCost())) return; + final Monster target = world.model.uiSelections.selectedMonster; + + final AttackResult attack = playerAttacks(target); this.lastAttackResult = attack; - Resources r = context.mainActivity.getResources(); if (attack.isHit) { - String msg; + combatActionListeners.onPlayerAttackSuccess(target, attack); - final String monsterName = target.getName(); - if (attack.isCriticalHit) { - msg = r.getString(R.string.combat_result_herohitcritical, monsterName, attack.damage); - } else { - msg = r.getString(R.string.combat_result_herohit, monsterName, attack.damage); - } - if (attack.targetDied) { - msg += " " + r.getString(R.string.combat_result_herokillsmonster, monsterName, attack.damage); - } - message(msg); - - context.mainActivity.updateStatus(); if (lastAttackResult.targetDied) { - playerKilledMonster(currentlyAttackedMonster); + playerKilledMonster(target); } - startAttackEffect(attack, model.uiSelections.selectedPosition, this, CALLBACK_PLAYERATTACK); + startAttackEffect(attack, world.model.uiSelections.selectedPosition, this, CALLBACK_PLAYERATTACK); } else { - message(r.getString(R.string.combat_result_heromiss)); + combatActionListeners.onPlayerAttackMissed(target, attack); playerAttackCompleted(); } } @@ -216,65 +193,62 @@ public final class CombatController implements VisualEffectCompletedCallback { } public void playerKilledMonster(Monster killedMonster) { - final Player player = model.player; + final Player player = world.model.player; - Loot loot = model.currentMap.getBagOrCreateAt(killedMonster.position); + Loot loot = world.model.currentMap.getBagOrCreateAt(killedMonster.position); killedMonster.createLoot(loot, player); - model.currentMap.remove(killedMonster); - VisualEffectController.addSplatter(model.currentMap, killedMonster); + view.monsterSpawnController.remove(world.model.currentMap, killedMonster); + view.effectController.addSplatter(world.model.currentMap, killedMonster); - 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); + view.actorStatsController.addActorAP(player, player.getSkillLevel(SkillCollection.SKILL_CLEAVE) * SkillCollection.PER_SKILLPOINT_INCREASE_CLEAVE_AP); + view.actorStatsController.addActorHealth(player, player.getSkillLevel(SkillCollection.SKILL_EATER) * SkillCollection.PER_SKILLPOINT_INCREASE_EATER_HEALTH); + + world.model.statistics.addMonsterKill(killedMonster.getMonsterTypeID()); + view.actorStatsController.addExperience(loot.exp); - model.statistics.addMonsterKill(killedMonster.getMonsterTypeID()); - model.player.addExperience(loot.exp); totalExpThisFight += loot.exp; loot.exp = 0; - context.actorStatsController.applyKillEffectsToPlayer(player); + view.actorStatsController.applyKillEffectsToPlayer(player); - context.mainActivity.updateStatus(); - if (!loot.hasItems()) { - model.currentMap.removeGroundLoot(loot); - } else { - ItemController.updateLootVisibility(context, loot); - if (model.uiSelections.isInCombat) killedMonsterBags.add(loot); + world.model.currentMap.removeGroundLoot(loot); + } else if (world.model.uiSelections.isInCombat) { + killedMonsterBags.add(loot); } - context.mainActivity.redrawAll(MainView.REDRAW_ALL_MONSTER_KILLED); + combatActionListeners.onPlayerKilledMonster(killedMonster); } private boolean playerHasApLeft() { - final Player player = model.player; + final Player player = world.model.player; 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() { - context.mainActivity.updateStatus(); if (!playerHasApLeft()) beginMonsterTurn(false); } private void continueTurn() { - if (model.uiSelections.isPlayersCombatTurn) return; + if (world.model.uiSelections.isPlayersCombatTurn) return; if (playerHasApLeft()) return; handleNextMonsterAction(); } private void executeCombatMove(final Coord dest) { - if (model.uiSelections.selectedMonster != null) return; + if (world.model.uiSelections.selectedMonster != null) return; if (dest == null) return; - if (!useAPs(model.player.getMoveCost())) return; + if (!useAPs(world.model.player.getMoveCost())) return; - int fleeChanceBias = model.player.getSkillLevel(SkillCollection.SKILL_EVASION) * SkillCollection.PER_SKILLPOINT_INCREASE_EVASION_FLEE_CHANCE_PERCENTAGE; + int fleeChanceBias = world.model.player.getSkillLevel(SkillCollection.SKILL_EVASION) * SkillCollection.PER_SKILLPOINT_INCREASE_EVASION_FLEE_CHANCE_PERCENTAGE; if (Constants.roll100(Constants.FLEE_FAIL_CHANCE_PERCENT - fleeChanceBias)) { fleeingFailed(); return; } - model.player.nextPosition.set(dest); - context.movementController.moveToNextIfPossible(false); + world.model.player.nextPosition.set(dest); + view.movementController.moveToNextIfPossible(false); if (canExitCombat()) exitCombat(true); @@ -282,12 +256,12 @@ public final class CombatController implements VisualEffectCompletedCallback { } private void fleeingFailed() { - Resources r = context.mainActivity.getResources(); - message(r.getString(R.string.combat_flee_failed)); + combatActionListeners.onPlayerFailedFleeing(); beginMonsterTurn(false); } private final Handler monsterTurnHandler = new Handler() { + @Override public void handleMessage(Message msg) { monsterTurnHandler.removeMessages(0); CombatController.this.handleNextMonsterAction(); @@ -295,14 +269,14 @@ public final class CombatController implements VisualEffectCompletedCallback { }; public void beginMonsterTurn(boolean isFirstRound) { - model.player.ap.current = 0; - model.uiSelections.isPlayersCombatTurn = false; - for (MonsterSpawnArea a : model.currentMap.spawnAreas) { + view.actorStatsController.setActorMinAP(world.model.player); + world.model.uiSelections.isPlayersCombatTurn = false; + for (MonsterSpawnArea a : world.model.currentMap.spawnAreas) { for (Monster m : a.monsters) { - m.setMaxAP(); + view.actorStatsController.setActorMaxAP(m); } } - if (!isFirstRound) context.gameRoundController.onNewMonsterRound(); + if (!isFirstRound) view.gameRoundController.onNewMonsterRound(); handleNextMonsterAction(); } @@ -311,11 +285,11 @@ public final class CombatController implements VisualEffectCompletedCallback { if (previousMonster.hasAPs(previousMonster.getAttackCost())) return previousMonster; } - for (MonsterSpawnArea a : model.currentMap.spawnAreas) { + for (MonsterSpawnArea a : world.model.currentMap.spawnAreas) { for (Monster m : a.monsters) { if (!m.isAgressive()) continue; - if (m.isAdjacentTo(model.player)) { + if (m.isAdjacentTo(world.model.player)) { if (m.hasAPs(m.getAttackCost())) return m; } } @@ -324,35 +298,27 @@ public final class CombatController implements VisualEffectCompletedCallback { } private void handleNextMonsterAction() { - if (!context.model.uiSelections.isMainActivityVisible) return; + if (!world.model.uiSelections.isMainActivityVisible) return; currentActiveMonster = determineNextMonster(currentActiveMonster); if (currentActiveMonster == null) { endMonsterTurn(); return; } - currentActiveMonster.useAPs(currentActiveMonster.getAttackCost()); + view.actorStatsController.useAPs(currentActiveMonster, currentActiveMonster.getAttackCost()); - context.mainActivity.combatview.updateTurnInfo(currentActiveMonster); - Resources r = context.mainActivity.getResources(); - AttackResult attack = monsterAttacks(model, currentActiveMonster); + combatTurnListeners.onMonsterIsAttacking(currentActiveMonster); + AttackResult attack = monsterAttacks(currentActiveMonster); this.lastAttackResult = attack; - String monsterName = currentActiveMonster.getName(); if (attack.isHit) { - if (attack.isCriticalHit) { - message(r.getString(R.string.combat_result_monsterhitcritical, monsterName, attack.damage)); - } else { - message(r.getString(R.string.combat_result_monsterhit, monsterName, attack.damage)); - } - context.mainActivity.updateStatus(); + combatActionListeners.onMonsterAttackSuccess(currentActiveMonster, attack); - startAttackEffect(attack, model.player.position, this, CALLBACK_MONSTERATTACK); + startAttackEffect(attack, world.model.player.position, this, CALLBACK_MONSTERATTACK); } else { - message(r.getString(R.string.combat_result_monstermiss, monsterName)); - context.mainActivity.updateStatus(); + combatActionListeners.onMonsterAttackMissed(currentActiveMonster, attack); - monsterTurnHandler.sendEmptyMessageDelayed(0, context.preferences.attackspeed_milliseconds); + monsterTurnHandler.sendEmptyMessageDelayed(0, view.preferences.attackspeed_milliseconds); } } @@ -370,20 +336,19 @@ public final class CombatController implements VisualEffectCompletedCallback { private void monsterAttackCompleted() { if (lastAttackResult.targetDied) { - context.controller.handlePlayerDeath(); + view.controller.handlePlayerDeath(); return; } handleNextMonsterAction(); } private void startAttackEffect(AttackResult attack, final Coord position, VisualEffectCompletedCallback callback, int callbackValue) { - if (context.preferences.attackspeed_milliseconds <= 0) { + if (view.preferences.attackspeed_milliseconds <= 0) { callback.onVisualEffectCompleted(callbackValue); return; } - context.effectController.startEffect( - context.mainActivity.mainview - , position + view.effectController.startEffect( + position , VisualEffectCollection.EFFECT_BLOOD , attack.damage , callback @@ -395,14 +360,10 @@ public final class CombatController implements VisualEffectCompletedCallback { } private void newPlayerTurn(boolean isFirstRound) { - model.player.setMaxAP(); - if (!isFirstRound) context.gameRoundController.onNewPlayerRound(); - model.uiSelections.isPlayersCombatTurn = true; - updateTurnInfo(); - } - private void updateTurnInfo() { - context.mainActivity.combatview.updateTurnInfo(currentActiveMonster); - context.mainActivity.updateStatus(); + view.actorStatsController.setActorMaxAP(world.model.player); + if (!isFirstRound) view.gameRoundController.onNewPlayerRound(); + world.model.uiSelections.isPlayersCombatTurn = true; + combatTurnListeners.onNewPlayerTurn(); } private static boolean hasCriticalAttack(Actor attacker, Actor target) { @@ -432,26 +393,26 @@ public final class CombatController implements VisualEffectCompletedCallback { if (averageDamagePerTurn <= 0) return 100; return (int) FloatMath.ceil(target.getMaxHP() / averageDamagePerTurn); } - public static int getMonsterDifficulty(WorldContext world, Monster monster) { + public int getMonsterDifficulty(Monster monster) { // returns [0..100) . 100 == easy. int turnsToKillMonster = getTurnsToKillTarget(world.model.player, monster); if (turnsToKillMonster >= 999) return 0; int turnsToKillPlayer = getTurnsToKillTarget(monster, world.model.player); int result = 50 + (turnsToKillPlayer - turnsToKillMonster) * 2; if (result <= 1) return 1; - else if (result > 100) return 100; + if (result > 100) return 100; return result; } - private AttackResult playerAttacks(WorldContext world, Monster currentMonster) { + private AttackResult playerAttacks(Monster currentMonster) { AttackResult result = attack(world.model.player, currentMonster); - SkillController.applySkillEffectsFromPlayerAttack(result, world, currentMonster); + view.skillController.applySkillEffectsFromPlayerAttack(result, currentMonster); return result; } - private AttackResult monsterAttacks(ModelContainer model, Monster currentMonster) { - AttackResult result = attack(currentMonster, model.player); - SkillController.applySkillEffectsFromMonsterAttack(result, world, currentMonster); + private AttackResult monsterAttacks(Monster currentMonster) { + AttackResult result = attack(currentMonster, world.model.player); + view.skillController.applySkillEffectsFromMonsterAttack(result, currentMonster); return result; } @@ -479,7 +440,7 @@ public final class CombatController implements VisualEffectCompletedCallback { } damage -= target.getDamageResistance(); if (damage < 0) damage = 0; - target.health.subtract(damage, false); + view.actorStatsController.removeActorHealth(target, damage); applyAttackHitStatusEffects(attacker, target); @@ -491,7 +452,7 @@ public final class CombatController implements VisualEffectCompletedCallback { if (onHitEffects == null) return; for (ItemTraits_OnUse e : onHitEffects) { - context.actorStatsController.applyUseEffect(attacker, target, e); + view.actorStatsController.applyUseEffect(attacker, target, e); } } @@ -502,7 +463,6 @@ public final class CombatController implements VisualEffectCompletedCallback { public void startFlee() { setCombatSelection(null, null); - Resources r = context.mainActivity.getResources(); - message(r.getString(R.string.combat_begin_flee)); + combatActionListeners.onPlayerStartedFleeing(); } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/Constants.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/Constants.java index 6d555ff9d..72dcc217c 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/Constants.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/Constants.java @@ -29,6 +29,7 @@ public final class Constants { public static final int FULLROUND_DURATION = 25000; public static final int TICKS_PER_ROUND = ROUND_DURATION / TICK_DELAY; 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 long MAP_UNVISITED_RESPAWN_DURATION_MS = 3 * 60 * 1000; // 3 min in milliseconds diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/Controller.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/Controller.java index 4672b3f75..7e9111117 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/Controller.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/Controller.java @@ -1,13 +1,8 @@ package com.gpl.rpg.AndorsTrail.controller; -import android.app.Activity; - -import com.gpl.rpg.AndorsTrail.Dialogs; -import com.gpl.rpg.AndorsTrail.R; -import com.gpl.rpg.AndorsTrail.activity.MainActivity; 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.controller.listeners.WorldEventListeners; import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection; import com.gpl.rpg.AndorsTrail.model.actor.Monster; import com.gpl.rpg.AndorsTrail.model.actor.Player; @@ -19,90 +14,91 @@ public final class Controller { private final ViewContext view; private final WorldContext world; - private final ModelContainer model; + public final WorldEventListeners worldEventListeners = new WorldEventListeners(); - public Controller(ViewContext context) { + public Controller(ViewContext context, WorldContext world) { this.view = context; - this.world = context; - this.model = world.model; + this.world = world; } public void handleMapEvent(MapObject o, Coord position) { switch (o.type) { case MapObject.MAPEVENT_SIGN: if (o.id == null || o.id.length() <= 0) return; - Dialogs.showMapSign(view.mainActivity, view, o.id); + worldEventListeners.onPlayerSteppedOnMapSignArea(o); break; case MapObject.MAPEVENT_NEWMAP: if (o.map == null || o.place == null) return; int offset_x = position.x - o.position.topLeft.x; int offset_y = position.y - o.position.topLeft.y; - view.movementController.placePlayerAt(MapObject.MAPEVENT_NEWMAP, o.map, o.place, offset_x, offset_y); + view.movementController.placePlayerAsyncAt(MapObject.MAPEVENT_NEWMAP, o.map, o.place, offset_x, offset_y); break; case MapObject.MAPEVENT_REST: - Dialogs.showRest(view.mainActivity, view, o); + steppedOnRestArea(o); break; } } + + private void steppedOnRestArea(MapObject area) { + if (view.preferences.confirmRest) { + worldEventListeners.onPlayerSteppedOnRestArea(area); + } else { + rest(area); + } + } public void steppedOnMonster(Monster m, Coord p) { if (m.isAgressive()) { view.combatController.setCombatSelection(m, p); - if (!view.preferences.confirmAttack) { - view.combatController.enterCombat(CombatController.BEGIN_TURN_PLAYER); + if (view.preferences.confirmAttack) { + worldEventListeners.onPlayerSteppedOnMonster(m); } else { - Dialogs.showMonsterEncounter(view.mainActivity, view, m); + view.combatController.enterCombat(CombatController.BEGIN_TURN_PLAYER); } } else { - Dialogs.showConversation(view.mainActivity, view, m.getPhraseID(), m); + worldEventListeners.onPlayerStartedConversation(m, m.getPhraseID()); } } public void handlePlayerDeath() { view.combatController.exitCombat(false); - final Player player = model.player; - int lostExp = player.levelExperience.current * Constants.PERCENT_EXP_LOST_WHEN_DIED / 100; + final Player player = world.model.player; + int lostExp = player.getCurrentLevelExperience() * Constants.PERCENT_EXP_LOST_WHEN_DIED / 100; lostExp -= lostExp * player.getSkillLevel(SkillCollection.SKILL_LOWER_EXPLOSS) * SkillCollection.PER_SKILLPOINT_INCREASE_EXPLOSS_PERCENT / 100; if (lostExp < 0) lostExp = 0; - player.addExperience(-lostExp); - model.statistics.addPlayerDeath(lostExp); - final MainActivity act = view.mainActivity; - MovementController.respawnPlayer(act.getResources(), world); - playerRested(world, null); - act.updateStatus(); - act.mainview.notifyMapChanged(world.model); - act.message(act.getResources().getString(R.string.combat_hero_dies, lostExp)); + view.actorStatsController.addExperience(-lostExp); + world.model.statistics.addPlayerDeath(lostExp); + view.movementController.respawnPlayerAsync(); + lotsOfTimePassed(); + worldEventListeners.onPlayerDied(lostExp); } - public static void playerRested(final WorldContext world, MapObject area) { + public void lotsOfTimePassed() { final Player player = world.model.player; - ActorStatsController.removeAllTemporaryConditions(player); - ActorStatsController.recalculatePlayerStats(player); - player.setMaxAP(); - player.setMaxHP(); - if (area != null) { - player.setSpawnPlace(world.model.currentMap.name, area.id); - } + view.actorStatsController.removeAllTemporaryConditions(player); + view.actorStatsController.recalculatePlayerStats(player); + view.actorStatsController.setActorMaxAP(player); + view.actorStatsController.setActorMaxHealth(player); for (PredefinedMap m : world.maps.predefinedMaps) { m.resetTemporaryData(); } - world.model.currentMap.spawnAll(world); + view.monsterSpawnController.spawnAll(world.model.currentMap); } - public static void ui_playerRested(final Activity currentActivity, final ViewContext viewContext, MapObject area) { - playerRested(viewContext, area); - viewContext.mainActivity.updateStatus(); - Dialogs.showRested(currentActivity, viewContext); + public void rest(MapObject area) { + lotsOfTimePassed(); + world.model.player.setSpawnPlace(world.model.currentMap.name, area.id); + worldEventListeners.onPlayerRested(); } - public boolean handleKeyArea(MapObject area) { - if (view.model.player.hasExactQuestProgress(area.requireQuestProgress)) return true; - Dialogs.showKeyArea(view.mainActivity, view, area.id); + public boolean canEnterKeyArea(MapObject area) { + if (world.model.player.hasExactQuestProgress(area.requireQuestProgress)) return true; + worldEventListeners.onPlayerSteppedOnKeyArea(area); return false; } - public static void resetMapsNotRecentlyVisited(final WorldContext world) { + public void resetMapsNotRecentlyVisited() { for (PredefinedMap m : world.maps.predefinedMaps) { if (m == world.model.currentMap) continue; if (m.isRecentlyVisited()) continue; @@ -110,11 +106,4 @@ public final class Controller { m.resetTemporaryData(); } } - - public boolean moveAndSpawnMonsters() { - boolean hasChanged = false; - if (view.monsterMovementController.moveMonsters()) hasChanged = true; - if (model.currentMap.maybeSpawn(world)) hasChanged = true; - return hasChanged; - } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java index ca0375f7e..91939655a 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java @@ -1,5 +1,6 @@ package com.gpl.rpg.AndorsTrail.controller; +import com.gpl.rpg.AndorsTrail.context.ViewContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; import com.gpl.rpg.AndorsTrail.conversation.Phrase; import com.gpl.rpg.AndorsTrail.conversation.Phrase.Reply; @@ -16,9 +17,17 @@ import com.gpl.rpg.AndorsTrail.util.ConstRange; public final class ConversationController { + private final ViewContext view; + private final WorldContext world; + + public ConversationController(ViewContext view, WorldContext world) { + this.view = view; + this.world = world; + } + private static final ConstRange always = new ConstRange(1, 1); - public static Loot applyPhraseRewards(final Player player, final Phrase phrase, final WorldContext world) { + public Loot applyPhraseRewards(final Player player, final Phrase phrase) { if (phrase.rewards == null || phrase.rewards.length == 0) return null; final Loot loot = new Loot(); @@ -32,11 +41,11 @@ public final class ConversationController { ActorConditionType conditionType = world.actorConditionsTypes.getActorConditionType(reward.rewardID); ActorConditionEffect e = new ActorConditionEffect(conditionType, magnitude, duration, always); - ActorStatsController.applyActorCondition(player, e); + view.actorStatsController.applyActorCondition(player, e); break; case Reward.REWARD_TYPE_SKILL_INCREASE: int skillID = Integer.parseInt(reward.rewardID); - SkillController.levelUpSkillByQuest(player, world.skills.getSkill(skillID)); + view.skillController.levelUpSkillByQuest(player, world.skills.getSkill(skillID)); break; case Reward.REWARD_TYPE_DROPLIST: world.dropLists.getDropList(reward.rewardID).createRandomLoot(loot, player); @@ -58,7 +67,7 @@ public final class ConversationController { } player.inventory.add(loot); - player.addExperience(loot.exp); + view.actorStatsController.addExperience(loot.exp); return loot; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/GameRoundController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/GameRoundController.java index 930434df2..e65acf1dc 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/GameRoundController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/GameRoundController.java @@ -2,29 +2,29 @@ package com.gpl.rpg.AndorsTrail.controller; 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.controller.listeners.GameRoundListeners; import com.gpl.rpg.AndorsTrail.util.TimedMessageTask; -import com.gpl.rpg.AndorsTrail.view.MainView; public final class GameRoundController implements TimedMessageTask.Callback { private final ViewContext view; private final WorldContext world; - private final ModelContainer model; private final TimedMessageTask roundTimer; + public final GameRoundListeners gameRoundListeners = new GameRoundListeners(); - public GameRoundController(ViewContext context) { + public GameRoundController(ViewContext context, WorldContext world) { this.view = context; - this.world = context; - this.model = world.model; + this.world = world; this.roundTimer = new TimedMessageTask(this, Constants.TICK_DELAY, true); } private int ticksUntilNextRound = Constants.TICKS_PER_ROUND; private int ticksUntilNextFullRound = Constants.TICKS_PER_FULLROUND; - public boolean onTick(TimedMessageTask task) { - if (!model.uiSelections.isMainActivityVisible) return false; - if (model.uiSelections.isInCombat) return false; + + @Override + public boolean onTick(TimedMessageTask task) { + if (!world.model.uiSelections.isMainActivityVisible) return false; + if (world.model.uiSelections.isInCombat) return false; onNewTick(); @@ -44,8 +44,7 @@ public final class GameRoundController implements TimedMessageTask.Callback { } public void resume() { - view.mainActivity.updateStatus(); - model.uiSelections.isMainActivityVisible = true; + world.model.uiSelections.isMainActivityVisible = true; restartWaitForNextRound(); restartWaitForNextFullRound(); roundTimer.start(); @@ -61,33 +60,34 @@ public final class GameRoundController implements TimedMessageTask.Callback { public void pause() { roundTimer.stop(); - model.uiSelections.isMainActivityVisible = false; + world.model.uiSelections.isMainActivityVisible = false; } public void onNewFullRound() { - Controller.resetMapsNotRecentlyVisited(world); - view.actorStatsController.applyConditionsToMonsters(model.currentMap, true); - view.actorStatsController.applyConditionsToPlayer(model.player, true); + view.controller.resetMapsNotRecentlyVisited(); + view.actorStatsController.applyConditionsToMonsters(world.model.currentMap, true); + view.actorStatsController.applyConditionsToPlayer(world.model.player, true); + gameRoundListeners.onNewFullRound(); } public void onNewRound() { onNewMonsterRound(); onNewPlayerRound(); + gameRoundListeners.onNewRound(); } public void onNewPlayerRound() { - view.actorStatsController.applyConditionsToPlayer(model.player, false); - view.actorStatsController.applySkillEffectsForNewRound(model.player, model.currentMap); + view.actorStatsController.applyConditionsToPlayer(world.model.player, false); + view.actorStatsController.applySkillEffectsForNewRound(world.model.player, world.model.currentMap); } public void onNewMonsterRound() { - view.actorStatsController.applyConditionsToMonsters(model.currentMap, false); + view.actorStatsController.applyConditionsToMonsters(world.model.currentMap, false); } private void onNewTick() { - boolean hasChanged = false; - if (view.controller.moveAndSpawnMonsters()) hasChanged = true; + view.monsterMovementController.moveMonsters(); + view.monsterSpawnController.maybeSpawn(world.model.currentMap); view.monsterMovementController.attackWithAgressiveMonsters(); - if (VisualEffectController.updateSplatters(model.currentMap)) hasChanged = true; - - if (hasChanged) view.mainActivity.redrawAll(MainView.REDRAW_ALL_MONSTER_MOVED); //TODO: should only redraw spawned tiles + view.effectController.updateSplatters(world.model.currentMap); + gameRoundListeners.onNewTick(); } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/InputController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/InputController.java index b128fd963..a20432739 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/InputController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/InputController.java @@ -7,23 +7,20 @@ import android.view.View.OnLongClickListener; 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.util.Coord; public final class InputController implements OnClickListener, OnLongClickListener{ private final ViewContext view; private final WorldContext world; - private final ModelContainer model; private final Coord lastTouchPosition_tileCoords = new Coord(); private int lastTouchPosition_dx = 0; private int lastTouchPosition_dy = 0; private long lastTouchEventTime = 0; - public InputController(ViewContext context) { - this.view = context; - this.world = context; - this.model = world.model; + public InputController(ViewContext view, WorldContext world) { + this.view = view; + this.world = world; } public boolean onKeyboardAction(int keyCode) { @@ -54,7 +51,7 @@ public final class InputController implements OnClickListener, OnLongClickListen } public void onRelativeMovement(int dx, int dy) { if (!allowInputInterval()) return; - if (model.uiSelections.isInCombat) { + if (world.model.uiSelections.isInCombat) { view.combatController.executeMoveAttack(dx, dy); } else { view.movementController.startMovement(dx, dy, null); @@ -67,13 +64,13 @@ public final class InputController implements OnClickListener, OnLongClickListen @Override public void onClick(View arg0) { - if (!model.uiSelections.isInCombat) return; + if (!world.model.uiSelections.isInCombat) return; onRelativeMovement(lastTouchPosition_dx, lastTouchPosition_dy); } @Override public boolean onLongClick(View arg0) { - if (model.uiSelections.isInCombat) { + if (world.model.uiSelections.isInCombat) { //TODO: Should be able to mark positions far away (mapwalk / ranged combat) if (lastTouchPosition_dx == 0 && lastTouchPosition_dy == 0) return false; if (Math.abs(lastTouchPosition_dx) > 1) return false; @@ -98,10 +95,10 @@ public final class InputController implements OnClickListener, OnLongClickListen public boolean onTouchedTile(int tile_x, int tile_y) { lastTouchPosition_tileCoords.set(tile_x, tile_y); - lastTouchPosition_dx = tile_x - model.player.position.x; - lastTouchPosition_dy = tile_y - model.player.position.y; + lastTouchPosition_dx = tile_x - world.model.player.position.x; + lastTouchPosition_dy = tile_y - world.model.player.position.y; - if (model.uiSelections.isInCombat) return false; + if (world.model.uiSelections.isInCombat) return false; view.movementController.startMovement(lastTouchPosition_dx, lastTouchPosition_dy, lastTouchPosition_tileCoords); return true; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ItemController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ItemController.java index 7ad6e2636..2643caf53 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ItemController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ItemController.java @@ -1,10 +1,13 @@ package com.gpl.rpg.AndorsTrail.controller; import java.util.ArrayList; +import java.util.Collection; -import com.gpl.rpg.AndorsTrail.Dialogs; +import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences; import com.gpl.rpg.AndorsTrail.context.ViewContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; +import com.gpl.rpg.AndorsTrail.controller.listeners.LootBagListeners; +import com.gpl.rpg.AndorsTrail.controller.listeners.QuickSlotListeners; import com.gpl.rpg.AndorsTrail.model.ModelContainer; import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection; import com.gpl.rpg.AndorsTrail.model.ability.traits.AbilityModifierTraits; @@ -15,31 +18,31 @@ import com.gpl.rpg.AndorsTrail.model.item.ItemTraits_OnUse; import com.gpl.rpg.AndorsTrail.model.item.ItemType; import com.gpl.rpg.AndorsTrail.model.item.Loot; import com.gpl.rpg.AndorsTrail.model.item.ItemContainer.ItemEntry; -import com.gpl.rpg.AndorsTrail.view.MainView; public final class ItemController { private final ViewContext view; private final WorldContext world; - private final ModelContainer model; + public final QuickSlotListeners quickSlotListeners = new QuickSlotListeners(); + public final LootBagListeners lootBagListeners = new LootBagListeners(); - public ItemController(ViewContext context) { + public ItemController(ViewContext context, WorldContext world) { this.view = context; - this.world = context; - this.model = world.model; + this.world = world; } public void dropItem(ItemType type, int quantity) { - if (model.player.inventory.getItemQuantity(type.id) < quantity) return; - model.player.inventory.removeItem(type.id, quantity); - model.currentMap.itemDropped(type, quantity, model.player.position); + if (world.model.player.inventory.getItemQuantity(type.id) < quantity) return; + world.model.player.inventory.removeItem(type.id, quantity); + world.model.currentMap.itemDropped(type, quantity, world.model.player.position); } public void equipItem(ItemType type, int slot) { if (!type.isEquippable()) return; - final Player player = model.player; - if (model.uiSelections.isInCombat) { - if (!player.useAPs(player.getReequipCost())) return; + final Player player = world.model.player; + if (world.model.uiSelections.isInCombat) { + boolean changed = view.actorStatsController.useAPs(player, player.getReequipCost()); + if (!changed) return; } if (!player.inventory.removeItem(type.id, 1)) return; @@ -52,53 +55,78 @@ public final class ItemController { } player.inventory.wear[slot] = type; - ActorStatsController.addConditionsFromEquippedItem(player, type); - ActorStatsController.recalculatePlayerStats(player); + view.actorStatsController.addConditionsFromEquippedItem(player, type); + view.actorStatsController.recalculatePlayerStats(player); } public void unequipSlot(ItemType type, int slot) { if (!type.isEquippable()) return; - final Player player = model.player; + final Player player = world.model.player; if (player.inventory.isEmptySlot(slot)) return; - if (model.uiSelections.isInCombat) { - if (!player.useAPs(player.getReequipCost())) return; + if (world.model.uiSelections.isInCombat) { + boolean changed = view.actorStatsController.useAPs(player, player.getReequipCost()); + if (!changed) return; } unequipSlot(player, slot); - ActorStatsController.recalculatePlayerStats(player); + view.actorStatsController.recalculatePlayerStats(player); } - private static void unequipSlot(Player player, int slot) { + private void unequipSlot(Player player, int slot) { ItemType removedItemType = player.inventory.wear[slot]; if (removedItemType == null) return; player.inventory.addItem(removedItemType); player.inventory.wear[slot] = null; - ActorStatsController.removeConditionsFromUnequippedItem(player, removedItemType); + view.actorStatsController.removeConditionsFromUnequippedItem(player, removedItemType); } public void useItem(ItemType type) { if (!type.isUsable()) return; - final Player player = model.player; - if (model.uiSelections.isInCombat) { - if (!player.useAPs(player.getUseItemCost())) return; + final Player player = world.model.player; + if (world.model.uiSelections.isInCombat) { + boolean changed = view.actorStatsController.useAPs(player, player.getUseItemCost()); + if (!changed) return; } if (!player.inventory.removeItem(type.id, 1)) return; view.actorStatsController.applyUseEffect(player, null, type.effects_use); - model.statistics.addItemUsage(type); + world.model.statistics.addItemUsage(type); //TODO: provide feedback that the item has been used. //context.mainActivity.message(androidContext.getResources().getString(R.string.inventory_item_used, type.name)); } - public void handleLootBag(Loot loot) { - Dialogs.showGroundLoot(view.mainActivity, view, loot); - consumeNonItemLoot(loot, model); + public void playerSteppedOnLootBag(Loot loot) { + if (loot.isVisible && pickupLootBagWithoutConfirmation()) { + view.controller.worldEventListeners.onPlayerPickedUpGroundLoot(loot); + pickupAll(loot); + removeLootBagIfEmpty(loot); + } else { + view.controller.worldEventListeners.onPlayerSteppedOnGroundLoot(loot); + consumeNonItemLoot(loot); + } } - public static void applyInventoryEffects(Player player) { + public void lootMonsterBags(Collection killedMonsterBags, int totalExpThisFight) { + if (pickupLootBagWithoutConfirmation()) { + view.controller.worldEventListeners.onPlayerPickedUpMonsterLoot(killedMonsterBags, totalExpThisFight); + pickupAll(killedMonsterBags); + removeLootBagIfEmpty(killedMonsterBags); + view.gameRoundController.resume(); + } else { + view.controller.worldEventListeners.onPlayerFoundMonsterLoot(killedMonsterBags, totalExpThisFight); + consumeNonItemLoot(killedMonsterBags); + } + } + + private boolean pickupLootBagWithoutConfirmation() { + if (view.preferences.displayLoot == AndorsTrailPreferences.DISPLAYLOOT_DIALOG) return false; + return true; + } + + public void applyInventoryEffects(Player player) { ItemType weapon = getMainWeapon(player); if (weapon != null) { player.attackCost = 0; @@ -126,7 +154,7 @@ public final class ItemController { return null; } - private static void applyInventoryEffects(Player player, int slot) { + private void applyInventoryEffects(Player player, int slot) { ItemType type = player.inventory.wear[slot]; if (type == null) return; if (slot == Inventory.WEARSLOT_SHIELD) { @@ -135,7 +163,7 @@ public final class ItemController { if (SkillController.isDualWielding(mainHandItem, type)) return; } if (type.effects_equip != null && type.effects_equip.stats != null) - ActorStatsController.applyAbilityEffects(player, type.effects_equip.stats, 1); + view.actorStatsController.applyAbilityEffects(player, type.effects_equip.stats, 1); } public static void recalculateHitEffectsFromWornItems(Player player) { @@ -159,51 +187,44 @@ public final class ItemController { } } - public static void consumeNonItemLoot(Loot loot, ModelContainer model) { + public void consumeNonItemLoot(Loot loot) { // Experience will be given as soon as the monster is killed. - model.player.inventory.gold += loot.gold; + world.model.player.inventory.gold += loot.gold; loot.gold = 0; - removeEmptyLoot(loot, model); + removeLootBagIfEmpty(loot); } - public static void consumeNonItemLoot(Iterable lootBags, ModelContainer model) { + public void consumeNonItemLoot(Iterable lootBags) { for(Loot l : lootBags) { - consumeNonItemLoot(l, model); + consumeNonItemLoot(l); } } - public static void pickupAll(Loot loot, ModelContainer model) { - model.player.inventory.add(loot.items); - consumeNonItemLoot(loot, model); + public void pickupAll(Loot loot) { + world.model.player.inventory.add(loot.items); + consumeNonItemLoot(loot); loot.clear(); } - public static void pickupAll(Iterable lootBags, ModelContainer model) { + public void pickupAll(Iterable lootBags) { for(Loot l : lootBags) { - pickupAll(l, model); + pickupAll(l); } } - public static boolean removeEmptyLoot(Loot loot, ModelContainer model) { - if (!loot.hasItems()) { - model.currentMap.removeGroundLoot(loot); - return true; // The bag was removed. - } else { - return false; - } + public boolean removeLootBagIfEmpty(final Loot loot) { + if (loot.hasItems()) return false; + + world.model.currentMap.removeGroundLoot(loot); + lootBagListeners.onLootBagRemoved(world.model.currentMap, loot.position); + return true; // The bag was removed. } - public static boolean updateLootVisibility(final ViewContext context, final Iterable lootBags) { + public boolean removeLootBagIfEmpty(final Iterable lootBags) { boolean isEmpty = true; for (Loot l : lootBags) { - if (!updateLootVisibility(context, l)) isEmpty = false; + if (!removeLootBagIfEmpty(l)) isEmpty = false; } return isEmpty; } - public static boolean updateLootVisibility(final ViewContext context, final Loot loot) { - final boolean isBagRemoved = removeEmptyLoot(loot, context.model); - context.mainActivity.redrawTile(loot.position, MainView.REDRAW_TILE_BAG); - return isBagRemoved; - } - private static int getMarketPriceFactor(Player player) { return Constants.MARKET_PRICEFACTOR_PERCENT - player.getSkillLevel(SkillCollection.SKILL_BARTER) * SkillCollection.PER_SKILLPOINT_INCREASE_BARTER_PRICEFACTOR_PERCENTAGE; @@ -316,12 +337,12 @@ public final class ItemController { } public void quickitemUse(int quickSlotId) { - useItem(model.player.inventory.quickitem[quickSlotId]); - view.mainActivity.updateStatus(); + useItem(world.model.player.inventory.quickitem[quickSlotId]); + quickSlotListeners.onQuickSlotUsed(quickSlotId); } public void setQuickItem(ItemType itemType, int quickSlotId) { - model.player.inventory.quickitem[quickSlotId] = itemType; - view.mainActivity.updateStatus(); + world.model.player.inventory.quickitem[quickSlotId] = itemType; + quickSlotListeners.onQuickSlotChanged(quickSlotId); } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java index c9b7aed5c..15205a670 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java @@ -2,54 +2,65 @@ package com.gpl.rpg.AndorsTrail.controller; 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.controller.listeners.MonsterMovementListeners; import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection; import com.gpl.rpg.AndorsTrail.model.actor.Monster; +import com.gpl.rpg.AndorsTrail.model.map.MapObject; import com.gpl.rpg.AndorsTrail.model.map.MonsterSpawnArea; +import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; import com.gpl.rpg.AndorsTrail.util.Coord; +import com.gpl.rpg.AndorsTrail.util.CoordRect; public final class MonsterMovementController { private final ViewContext view; private final WorldContext world; - private final ModelContainer model; + public final MonsterMovementListeners monsterMovementListeners = new MonsterMovementListeners(); - public MonsterMovementController(ViewContext context) { - this.view = context; - this.world = context; - this.model = world.model; + public MonsterMovementController(ViewContext context, WorldContext world) { + this.view = context; + this.world = world; } - public boolean moveMonsters() { - boolean atLeastOneMonsterMoved = false; + public void moveMonsters() { long currentTime = System.currentTimeMillis(); - for (MonsterSpawnArea a : model.currentMap.spawnAreas) { + for (MonsterSpawnArea a : world.model.currentMap.spawnAreas) { for (Monster m : a.monsters) { if (m.nextActionTime <= currentTime) { - if (moveMonster(m, a, currentTime)) atLeastOneMonsterMoved = true; + moveMonster(m, a); } } } - - return atLeastOneMonsterMoved; } public void attackWithAgressiveMonsters() { - for (MonsterSpawnArea a : model.currentMap.spawnAreas) { + for (MonsterSpawnArea a : world.model.currentMap.spawnAreas) { for (Monster m : a.monsters) { if (!m.isAgressive()) continue; - if (!m.isAdjacentTo(model.player)) continue; + if (!m.isAdjacentTo(world.model.player)) continue; - int aggressionChanceBias = model.player.getSkillLevel(SkillCollection.SKILL_EVASION) * SkillCollection.PER_SKILLPOINT_INCREASE_EVASION_MONSTER_ATTACK_CHANCE_PERCENTAGE; + int aggressionChanceBias = world.model.player.getSkillLevel(SkillCollection.SKILL_EVASION) * SkillCollection.PER_SKILLPOINT_INCREASE_EVASION_MONSTER_ATTACK_CHANCE_PERCENTAGE; if (Constants.roll100(Constants.MONSTER_AGGRESSION_CHANCE_PERCENT - aggressionChanceBias)) { + monsterMovementListeners.onMonsterSteppedOnPlayer(m); view.combatController.monsterSteppedOnPlayer(m); return; } } } } + + public static boolean monsterCanMoveTo(final PredefinedMap map, final CoordRect p) { + if (!map.isWalkable(p)) return false; + if (map.getMonsterAt(p) != null) return false; + MapObject m = map.getEventObjectAt(p.topLeft); + if (m != null) { + if (m.type == MapObject.MAPEVENT_NEWMAP) return false; + } + return true; + } - private boolean moveMonster(final Monster m, final MonsterSpawnArea area, long currentTime) { + private void moveMonster(final Monster m, final MonsterSpawnArea area) { + PredefinedMap map = world.model.currentMap; m.nextActionTime += getMillisecondsPerMove(m); if (m.movementDestination == null) { // Monster has waited and should start to move again. @@ -69,25 +80,26 @@ public final class MonsterMovementController { ,m.position.y + sgn(m.movementDestination.y - m.position.y) ); - if (!model.currentMap.monsterCanMoveTo(m.nextPosition)) { + if (!monsterCanMoveTo(map, m.nextPosition)) { cancelCurrentMonsterMovement(m); - return false; + return; } - if (m.nextPosition.contains(model.player.position)) { + if (m.nextPosition.contains(world.model.player.position)) { if (!m.isAgressive()) { cancelCurrentMonsterMovement(m); - return false; + return; } + monsterMovementListeners.onMonsterSteppedOnPlayer(m); view.combatController.monsterSteppedOnPlayer(m); } else { + CoordRect previousPosition = new CoordRect(new Coord(m.position), m.rectPosition.size); m.position.set(m.nextPosition.topLeft); + monsterMovementListeners.onMonsterMoved(map, m, previousPosition); } - return true; } - return false; } - private void cancelCurrentMonsterMovement(final Monster m) { + private static void cancelCurrentMonsterMovement(final Monster m) { m.movementDestination = null; m.nextActionTime += getMillisecondsPerMove(m) * Constants.rollValue(Constants.monsterWaitTurns); } @@ -98,7 +110,7 @@ public final class MonsterMovementController { private static int sgn(int i) { if (i <= -1) return -1; - else if (i >= 1) return 1; + if (i >= 1) return 1; return 0; } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterSpawningController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterSpawningController.java new file mode 100644 index 000000000..67fc7b742 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterSpawningController.java @@ -0,0 +1,80 @@ +package com.gpl.rpg.AndorsTrail.controller; + +import com.gpl.rpg.AndorsTrail.context.ViewContext; +import com.gpl.rpg.AndorsTrail.context.WorldContext; +import com.gpl.rpg.AndorsTrail.controller.listeners.MonsterSpawnListeners; +import com.gpl.rpg.AndorsTrail.model.actor.Monster; +import com.gpl.rpg.AndorsTrail.model.actor.MonsterType; +import com.gpl.rpg.AndorsTrail.model.map.MonsterSpawnArea; +import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; +import com.gpl.rpg.AndorsTrail.util.Coord; +import com.gpl.rpg.AndorsTrail.util.CoordRect; +import com.gpl.rpg.AndorsTrail.util.Size; + +public final class MonsterSpawningController { + private final ViewContext view; + private final WorldContext world; + public final MonsterSpawnListeners monsterSpawnListeners = new MonsterSpawnListeners(); + + public MonsterSpawningController(ViewContext view, WorldContext world) { + this.view = view; + this.world = world; + } + + public void spawnAllInArea(PredefinedMap map, MonsterSpawnArea area, boolean respawnUniqueMonsters) { + while (area.isSpawnable(respawnUniqueMonsters)) { + final boolean wasAbleToSpawn = spawnInArea(map, area, null); + if (!wasAbleToSpawn) break; + } + view.actorStatsController.healAllMonsters(area); + } + + public void maybeSpawn(PredefinedMap map) { + for (MonsterSpawnArea a : map.spawnAreas) { + if (!a.isSpawnable(false)) continue; + if (!a.rollShouldSpawn()) continue; + spawnInArea(map, a, world.model.player.position); + } + } + + public void spawnAll(PredefinedMap map) { + boolean respawnUniqueMonsters = false; + if (!map.visited) respawnUniqueMonsters = true; + for (MonsterSpawnArea a : map.spawnAreas) { + spawnAllInArea(map, a, respawnUniqueMonsters); + } + } + + private boolean spawnInArea(PredefinedMap map, MonsterSpawnArea a, Coord playerPosition) { + return spawnInArea(map, a, a.getRandomMonsterType(world), playerPosition); + } + public boolean TEST_spawnInArea(PredefinedMap map, MonsterSpawnArea a, MonsterType type) { return spawnInArea(map, a, type, null); } + private boolean spawnInArea(PredefinedMap map, MonsterSpawnArea a, MonsterType type, Coord playerPosition) { + Coord p = getRandomFreePosition(map, a.area, type.tileSize, playerPosition); + if (p == null) return false; + Monster m = a.spawn(p, type); + monsterSpawnListeners.onMonsterSpawned(map, m); + return true; + } + + public static Coord getRandomFreePosition(PredefinedMap map, CoordRect area, Size requiredSize, Coord playerPosition) { + CoordRect p = new CoordRect(requiredSize); + for(int i = 0; i < 100; ++i) { + p.topLeft.set( + area.topLeft.x + Constants.rnd.nextInt(area.size.width) + ,area.topLeft.y + Constants.rnd.nextInt(area.size.height)); + if (!MonsterMovementController.monsterCanMoveTo(map, p)) continue; + if (playerPosition != null && p.contains(playerPosition)) continue; + return p.topLeft; + } + return null; // Couldn't find a free spot. + } + + public void remove(PredefinedMap map, Monster m) { + for (MonsterSpawnArea a : map.spawnAreas) { + a.remove(m); + } + monsterSpawnListeners.onMonsterRemoved(map, m, m.rectPosition); + } + +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java index 74d4dab55..3217350ee 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java @@ -6,6 +6,7 @@ import android.os.AsyncTask; import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences; import com.gpl.rpg.AndorsTrail.context.ViewContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; +import com.gpl.rpg.AndorsTrail.controller.listeners.PlayerMovementListeners; import com.gpl.rpg.AndorsTrail.model.ModelContainer; import com.gpl.rpg.AndorsTrail.model.actor.Monster; import com.gpl.rpg.AndorsTrail.model.actor.Player; @@ -23,24 +24,23 @@ import com.gpl.rpg.AndorsTrail.util.TimedMessageTask; public final class MovementController implements TimedMessageTask.Callback { private final ViewContext view; private final WorldContext world; - private final ModelContainer model; private final TimedMessageTask movementHandler; + public final PlayerMovementListeners playerMovementListeners = new PlayerMovementListeners(); - public MovementController(ViewContext context) { + public MovementController(ViewContext context, WorldContext world) { this.view = context; - this.world = context; - this.model = world.model; + this.world = world; this.movementHandler = new TimedMessageTask(this, Constants.MINIMUM_INPUT_INTERVAL, false); } - public void placePlayerAt(final int objectType, final String mapName, final String placeName, final int offset_x, final int offset_y) { + public void placePlayerAsyncAt(final int objectType, final String mapName, final String placeName, final int offset_x, final int offset_y) { AsyncTask task = new AsyncTask() { @Override protected Void doInBackground(Void... arg0) { stopMovement(); - placePlayerAt(view.mainActivity.getResources(), world, objectType, mapName, placeName, offset_x, offset_y); + placePlayerAt(view.getResources(), objectType, mapName, placeName, offset_x, offset_y); return null; } @@ -48,9 +48,8 @@ public final class MovementController implements TimedMessageTask.Callback { @Override protected void onPostExecute(Void result) { super.onPostExecute(result); - view.mainActivity.clearMessages(); - view.mainActivity.mainview.notifyMapChanged(model); stopMovement(); + playerMovementListeners.onPlayerEnteredNewMap(world.model.currentMap, world.model.player.position); view.gameRoundController.resume(); } @@ -59,7 +58,7 @@ public final class MovementController implements TimedMessageTask.Callback { task.execute(); } - public static void placePlayerAt(final Resources res, final WorldContext world, int objectType, String mapName, String placeName, int offset_x, int offset_y) { + public void placePlayerAt(final Resources res, int objectType, String mapName, String placeName, int offset_x, int offset_y) { if (mapName == null || placeName == null) return; PredefinedMap newMap = world.maps.findPredefinedMap(mapName); if (newMap == null) { @@ -74,33 +73,34 @@ public final class MovementController implements TimedMessageTask.Callback { final ModelContainer model = world.model; if (model.currentMap != null) model.currentMap.updateLastVisitTime(); - cacheCurrentMapData(res, world, newMap); + cacheCurrentMapData(res, newMap); model.currentMap = newMap; model.player.position.set(place.position.topLeft); model.player.position.x += Math.min(offset_x, place.position.size.width-1); model.player.position.y += Math.min(offset_y, place.position.size.height-1); model.player.lastPosition.set(model.player.position); - if (!newMap.visited) playerVisitsMapFirstTime(world, newMap); - else playerVisitsMap(world, newMap); + if (newMap.visited) playerVisitsMap(newMap); + else playerVisitsMapFirstTime(newMap); refreshMonsterAggressiveness(newMap, model.player); - VisualEffectController.updateSplatters(newMap); + view.effectController.updateSplatters(newMap); + } - private static void playerVisitsMapFirstTime(final WorldContext world, PredefinedMap m) { + private void playerVisitsMapFirstTime(PredefinedMap m) { m.reset(); - m.spawnAll(world); + view.monsterSpawnController.spawnAll(m); m.createAllContainerLoot(); m.visited = true; } - private static void playerVisitsMap(final WorldContext world, PredefinedMap m) { + private void playerVisitsMap(PredefinedMap m) { // Respawn everything if a certain time has elapsed. - if (!m.isRecentlyVisited()) m.spawnAll(world); + if (!m.isRecentlyVisited()) view.monsterSpawnController.spawnAll(m); } - public boolean mayMovePlayer() { - return !model.uiSelections.isInCombat; + private boolean mayMovePlayer() { + return !world.model.uiSelections.isInCombat; } private void movePlayer(int dx, int dy) { @@ -109,16 +109,16 @@ public final class MovementController implements TimedMessageTask.Callback { if (!findWalkablePosition(dx, dy)) return; - Monster m = model.currentMap.getMonsterAt(model.player.nextPosition); + Monster m = world.model.currentMap.getMonsterAt(world.model.player.nextPosition); if (m != null) { - view.controller.steppedOnMonster(m, model.player.nextPosition); + view.controller.steppedOnMonster(m, world.model.player.nextPosition); return; } moveToNextIfPossible(true); } - public boolean findWalkablePosition(int dx, int dy) { + private boolean findWalkablePosition(int dx, int dy) { // try to move with movementAggresiveness, if that fails fall back to MOVEMENTAGGRESSIVENESS_NORMAL if (findWalkablePosition(dx, dy, view.preferences.movementAggressiveness)) return true; @@ -127,21 +127,21 @@ public final class MovementController implements TimedMessageTask.Callback { return findWalkablePosition(dx, dy, AndorsTrailPreferences.MOVEMENTAGGRESSIVENESS_NORMAL); } - public boolean findWalkablePosition(int dx, int dy, int aggressiveness) { + public boolean findWalkablePosition(int dx, int dy, int aggressiveness) { if (view.preferences.movementMethod == AndorsTrailPreferences.MOVEMENTMETHOD_STRAIGHT) { return findWalkablePosition_straight(dx, dy, aggressiveness); } else { return findWalkablePosition_directional(dx, dy, aggressiveness); } } - public boolean findWalkablePosition_straight(int dx, int dy, int aggressiveness) { + private boolean findWalkablePosition_straight(int dx, int dy, int aggressiveness) { if (tryWalkablePosition(sgn(dx), sgn(dy), aggressiveness)) return true; // try moving into the direction player is pointing at if (dx == 0 || dy == 0) return false; // if moving purely east, west, north or south failed - do nothing if (abs(dx) == abs(dy) && tryWalkablePosition(sgn(dx), 0, aggressiveness)) return true; // try moving horizontally or vertically otherwise (prefer the direction where he is pointing more) if (abs(dx) > abs(dy)) return tryWalkablePosition(sgn(dx), 0, aggressiveness); return tryWalkablePosition(0, sgn(dy), aggressiveness); } - public boolean findWalkablePosition_directional(int dx, int dy, int aggressiveness) { + private boolean findWalkablePosition_directional(int dx, int dy, int aggressiveness) { if (tryWalkablePosition(sgn(dx), sgn(dy), aggressiveness)) return true; // try moving into the direction player is pointing at if (dx == 0) { // player wants to move north or south but there is an obstacle @@ -166,26 +166,26 @@ public final class MovementController implements TimedMessageTask.Callback { return false; } } - - private boolean tryWalkablePosition(int dx, int dy, int aggressiveness) { - final Player player = model.player; + + private boolean tryWalkablePosition(int dx, int dy, int aggressiveness) { + final Player player = world.model.player; player.nextPosition.set( player.position.x + dx ,player.position.y + dy ); - if (!model.currentMap.isWalkable(player.nextPosition)) return false; + if (!world.model.currentMap.isWalkable(player.nextPosition)) return false; // allow player to enter every field when he is NORMAL // prevent player from entering "non-monster-fields" when he is AGGRESSIVE // prevent player from entering "monster-fields" when he is DEFENSIVE if (aggressiveness == AndorsTrailPreferences.MOVEMENTAGGRESSIVENESS_NORMAL) return true; - Monster m = model.currentMap.getMonsterAt(player.nextPosition); + Monster m = world.model.currentMap.getMonsterAt(player.nextPosition); if (m != null && !m.isAgressive()) return true; // avoid MOVEMENTAGGRESSIVENESS settings for NPCs if (aggressiveness == AndorsTrailPreferences.MOVEMENTAGGRESSIVENESS_AGGRESSIVE && m == null) return false; - else if (aggressiveness == AndorsTrailPreferences.MOVEMENTAGGRESSIVENESS_DEFENSIVE && m != null) return false; + if (aggressiveness == AndorsTrailPreferences.MOVEMENTAGGRESSIVENESS_DEFENSIVE && m != null) return false; return true; } @@ -202,14 +202,14 @@ public final class MovementController implements TimedMessageTask.Callback { } public void moveToNextIfPossible(boolean handleEvents) { - final Player player = model.player; - final PredefinedMap currentMap = model.currentMap; + final Player player = world.model.player; + final PredefinedMap currentMap = world.model.currentMap; final Coord newPosition = player.nextPosition; for (MapObject o : currentMap.eventObjects) { if (o.type == MapObject.MAPEVENT_KEYAREA) { if (o.position.contains(newPosition)) { - if (!view.controller.handleKeyArea(o)) return; + if (!view.controller.canEnterKeyArea(o)) return; } } } @@ -217,7 +217,7 @@ public final class MovementController implements TimedMessageTask.Callback { player.lastPosition.set(player.position); player.position.set(newPosition); view.combatController.setCombatSelection(null, null); - view.mainActivity.mainview.notifyPlayerMoved(newPosition); + playerMovementListeners.onPlayerMoved(newPosition, player.lastPosition); if (handleEvents) { MapObject o = currentMap.getEventObjectAt(newPosition); @@ -228,15 +228,19 @@ public final class MovementController implements TimedMessageTask.Callback { } Loot loot = currentMap.getBagAt(newPosition); - if (loot != null) view.itemController.handleLootBag(loot); + if (loot != null) view.itemController.playerSteppedOnLootBag(loot); } } - public static void respawnPlayer(final Resources res, final WorldContext world) { - placePlayerAt(res, world, MapObject.MAPEVENT_REST, world.model.player.getSpawnMap(), world.model.player.getSpawnPlace(), 0, 0); + public void respawnPlayer(Resources res) { + placePlayerAt(res, MapObject.MAPEVENT_REST, world.model.player.getSpawnMap(), world.model.player.getSpawnPlace(), 0, 0); + playerMovementListeners.onPlayerEnteredNewMap(world.model.currentMap, world.model.player.position); + } + public void respawnPlayerAsync() { + placePlayerAsyncAt(MapObject.MAPEVENT_REST, world.model.player.getSpawnMap(), world.model.player.getSpawnPlace(), 0, 0); } - public static void moveBlockedActors(final WorldContext world) { + public void moveBlockedActors() { final ModelContainer model = world.model; 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. @@ -257,7 +261,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.tileSize, playerPosition); + Coord p = MonsterSpawningController.getRandomFreePosition(map, a.area, m.tileSize, playerPosition); if (p == null) continue; m.position.set(p); } @@ -266,7 +270,7 @@ public final class MovementController implements TimedMessageTask.Callback { } } - public static void cacheCurrentMapData(final Resources res, final WorldContext world, final PredefinedMap nextMap) { + public void cacheCurrentMapData(final Resources res, final PredefinedMap nextMap) { LayeredTileMap mapTiles = TMXMapTranslator.readLayeredTileMap(res, world.tileManager.tileCache, nextMap); TileCollection cachedTiles = world.tileManager.loadTilesFor(nextMap, mapTiles, world, res); world.model.currentTileMap = mapTiles; @@ -280,7 +284,7 @@ public final class MovementController implements TimedMessageTask.Callback { private int movementDx; private int movementDy; public void startMovement(int dx, int dy, Coord destination) { - if (model.uiSelections.isInCombat) return; + if (!mayMovePlayer()) return; if (dx == 0 && dy == 0) return; movementDx = dx; @@ -291,10 +295,11 @@ public final class MovementController implements TimedMessageTask.Callback { public void stopMovement() { movementHandler.stop(); } - + + @Override public boolean onTick(TimedMessageTask task) { - if (!model.uiSelections.isMainActivityVisible) return false; - if (model.uiSelections.isInCombat) return false; + if (!world.model.uiSelections.isMainActivityVisible) return false; + if (world.model.uiSelections.isInCombat) return false; movePlayer(movementDx, movementDy); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/SkillController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/SkillController.java index b2d938aef..0d463ea0e 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/SkillController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/SkillController.java @@ -1,5 +1,6 @@ package com.gpl.rpg.AndorsTrail.controller; +import com.gpl.rpg.AndorsTrail.context.ViewContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; import com.gpl.rpg.AndorsTrail.model.AttackResult; import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionEffect; @@ -15,7 +16,15 @@ import com.gpl.rpg.AndorsTrail.model.item.DropList.DropItem; import com.gpl.rpg.AndorsTrail.util.ConstRange; public final class SkillController { - public static void applySkillEffects(Player player) { + private final ViewContext view; + private final WorldContext world; + + public SkillController(ViewContext view, WorldContext world) { + this.view = view; + this.world = world; + } + + public void applySkillEffects(Player player) { 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); @@ -27,7 +36,7 @@ public final class SkillController { 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)); + view.actorStatsController.addActorMaxAP(player, SkillCollection.PER_SKILLPOINT_INCREASE_SPEED * player.getSkillLevel(SkillCollection.SKILL_SPEED), false); /*final int berserkLevel = player.getSkillLevel(Skills.SKILL_BERSERKER); if (berserkLevel > 0) { final int berserkHealth = player.health.max * Skills.BERSERKER_STARTS_AT_HEALTH_PERCENT / 100; @@ -87,14 +96,20 @@ public final class SkillController { } return true; } - public static void levelUpSkillManually(Player player, SkillInfo skill) { + public void levelUpSkillManually(Player player, SkillInfo skill) { if (!canLevelupSkillManually(player, skill)) return; player.availableSkillIncreases -= 1; - player.addSkillLevel(skill.id); + addSkillLevel(skill.id); } - public static void levelUpSkillByQuest(Player player, SkillInfo skill) { + public void levelUpSkillByQuest(Player player, SkillInfo skill) { if (!canLevelupSkillWithQuest(player, skill)) return; - player.addSkillLevel(skill.id); + addSkillLevel(skill.id); + } + + private void addSkillLevel(int skillID) { + Player player = world.model.player; + player.skillLevels.put(skillID, player.skillLevels.get(skillID) + 1); + view.actorStatsController.recalculatePlayerStats(player); } public static int getActorConditionEffectChanceRollBias(ActorConditionEffect effect, Player player) { @@ -132,38 +147,38 @@ public final class SkillController { if (skillLevel <= 0) return false; return Constants.roll100(chancePerSkillLevel * skillLevel); } - private static void addConditionToActor(Actor target, WorldContext world, String conditionName, int magnitude, int duration) { + private void addConditionToActor(Actor target, String conditionName, int magnitude, int duration) { ActorConditionType conditionType = world.actorConditionsTypes.getActorConditionType(conditionName); ActorConditionEffect effect = new ActorConditionEffect(conditionType, magnitude, duration, null); - ActorStatsController.applyActorCondition(target, effect); + view.actorStatsController.applyActorCondition(target, effect); } - public static void applySkillEffectsFromPlayerAttack(AttackResult result, WorldContext world, Monster monster) { + public void applySkillEffectsFromPlayerAttack(AttackResult result, Monster monster) { if (!result.isHit) return; Player player = world.model.player; 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); + addConditionToActor(monster, "concussion", 1, 5); } } if (result.isCriticalHit) { if (rollForSkillChance(player, SkillCollection.SKILL_CRIT2, SkillCollection.PER_SKILLPOINT_INCREASE_CRIT2_CHANCE)) { - addConditionToActor(monster, world, "crit2", 1, 5); + addConditionToActor(monster, "crit2", 1, 5); } if (rollForSkillChance(player, SkillCollection.SKILL_CRIT1, SkillCollection.PER_SKILLPOINT_INCREASE_CRIT1_CHANCE)) { - addConditionToActor(monster, world, "crit1", 1, 5); + addConditionToActor(monster, "crit1", 1, 5); } } } - public static void applySkillEffectsFromMonsterAttack(AttackResult result, WorldContext world, Monster monster) { + public void applySkillEffectsFromMonsterAttack(AttackResult result, Monster monster) { if (!result.isHit) { if (rollForSkillChance(world.model.player, SkillCollection.SKILL_TAUNT, SkillCollection.PER_SKILLPOINT_INCREASE_TAUNT_CHANCE)) { - monster.ap.subtract(SkillCollection.TAUNT_AP_LOSS, false); + view.actorStatsController.changeActorAP(monster, -SkillCollection.TAUNT_AP_LOSS, false, false); } } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/VisualEffectController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/VisualEffectController.java index 692768fa0..92f8a4885 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/VisualEffectController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/VisualEffectController.java @@ -7,7 +7,9 @@ import android.os.Handler; import com.gpl.rpg.AndorsTrail.VisualEffectCollection; import com.gpl.rpg.AndorsTrail.VisualEffectCollection.VisualEffect; +import com.gpl.rpg.AndorsTrail.context.ViewContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; +import com.gpl.rpg.AndorsTrail.controller.listeners.VisualEffectFrameListeners; import com.gpl.rpg.AndorsTrail.model.actor.Monster; import com.gpl.rpg.AndorsTrail.model.actor.MonsterType; import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; @@ -15,19 +17,25 @@ 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.Size; -import com.gpl.rpg.AndorsTrail.view.MainView; public final class VisualEffectController { private int effectCount = 0; + private final ViewContext view; + private final WorldContext world; private final VisualEffectCollection effectTypes; - public VisualEffectController(WorldContext world) { + + public final VisualEffectFrameListeners visualEffectFrameListeners = new VisualEffectFrameListeners(); + + public VisualEffectController(ViewContext view, WorldContext world) { + this.view = view; + this.world = world; this.effectTypes = world.visualEffectTypes; } - public void startEffect(MainView mainview, Coord position, int effectID, int displayValue, VisualEffectCompletedCallback callback, int callbackValue) { + public void startEffect(Coord position, int effectID, int displayValue, VisualEffectCompletedCallback callback, int callbackValue) { ++effectCount; - (new VisualEffectAnimation(effectTypes.effects[effectID], position, mainview, displayValue, callback, callbackValue)) + (new VisualEffectAnimation(effectTypes.effects[effectID], position, displayValue, callback, callbackValue)) .start(); } @@ -53,12 +61,12 @@ public final class VisualEffectController { this.textPaint.setAlpha(255 * (effect.lastFrame - frame) / (effect.lastFrame - beginFadeAtFrame)); } area.topLeft.y = position.y - 1; - view.redrawAreaWithEffect(this, tileID, textYOffset, this.textPaint); + visualEffectFrameListeners.onNewAnimationFrame(this, tileID, textYOffset); } - protected void onCompleted() { + private void onCompleted() { --effectCount; - view.redrawArea(area, MainView.REDRAW_AREA_EFFECT_COMPLETED); + visualEffectFrameListeners.onAnimationCompleted(this); if (callback != null) callback.onVisualEffectCompleted(callbackValue); } @@ -69,17 +77,16 @@ public final class VisualEffectController { private int currentFrame = 0; private final VisualEffect effect; - private final MainView view; public final Coord position; public final String displayText; public final CoordRect area; - private final Paint textPaint = new Paint(); + public final Paint textPaint = new Paint(); private final int beginFadeAtFrame; private final VisualEffectCompletedCallback callback; private final int callbackValue; - public VisualEffectAnimation(VisualEffect effect, Coord position, MainView view, int displayValue, VisualEffectCompletedCallback callback, int callbackValue) { + public VisualEffectAnimation(VisualEffect effect, Coord position, int displayValue, VisualEffectCompletedCallback callback, int callbackValue) { this.position = position; this.callback = callback; this.callbackValue = callbackValue; @@ -88,10 +95,9 @@ public final class VisualEffectController { this.displayText = (displayValue == 0) ? null : String.valueOf(displayValue); this.textPaint.setColor(effect.textColor); this.textPaint.setShadowLayer(2, 1, 1, Color.DKGRAY); - this.textPaint.setTextSize(view.scaledTileSize * 0.5f); // 32dp. + this.textPaint.setTextSize(world.tileManager.viewTileSize * 0.5f); // 32dp. this.textPaint.setAlpha(255); this.textPaint.setTextAlign(Align.CENTER); - this.view = view; this.beginFadeAtFrame = effect.lastFrame / 2; } } @@ -106,9 +112,6 @@ public final class VisualEffectController { public static final class BloodSplatter { - public static final int TYPE_RED = 0; - public static final int TYPE_BROWN = 2; - public static final int TYPE_WHITE = 3; public final long removeAfter; public final long reduceIconAfter; public final Coord position; @@ -117,32 +120,33 @@ public final class VisualEffectController { public BloodSplatter(int iconID, Coord position) { this.iconID = iconID; this.position = position; - long now = System.currentTimeMillis(); - removeAfter = now + 20000; - reduceIconAfter = now + 10000; + final long now = System.currentTimeMillis(); + removeAfter = now + Constants.SPLATTER_DURATION_MS; + reduceIconAfter = now + Constants.SPLATTER_DURATION_MS / 2; } } - public static boolean updateSplatters(PredefinedMap map) { + public void updateSplatters(PredefinedMap map) { long now = System.currentTimeMillis(); - boolean hasChanges = false; for (int i = map.splatters.size() - 1; i >= 0; --i) { BloodSplatter b = map.splatters.get(i); if (b.removeAfter <= now) { map.splatters.remove(i); - hasChanges = true; + view.monsterSpawnController.monsterSpawnListeners.onSplatterRemoved(map, b.position); } else if (!b.reducedIcon && b.reduceIconAfter <= now) { b.reducedIcon = true; b.iconID++; - hasChanges = true; + view.monsterSpawnController.monsterSpawnListeners.onSplatterChanged(map, b.position); } } - return hasChanges; } - public static void addSplatter(PredefinedMap map, Monster m) { + public void addSplatter(PredefinedMap map, Monster m) { int iconID = getSplatterIconFromMonsterClass(m.getMonsterClass()); - if (iconID > 0) map.splatters.add(new BloodSplatter(iconID, m.position)); + if (iconID > 0) { + map.splatters.add(new BloodSplatter(iconID, m.position)); + view.monsterSpawnController.monsterSpawnListeners.onSplatterAdded(map, m.position); + } } private static int getSplatterIconFromMonsterClass(int monsterClass) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/WorldMapController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/WorldMapController.java index efeff266b..aa5491c80 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/WorldMapController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/WorldMapController.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; +import java.util.Collection; import java.util.HashSet; import android.content.Context; @@ -167,7 +168,7 @@ public final class WorldMapController { private static String getWorldMapSegmentAsHtml(Resources res, WorldContext world, String segmentName) throws IOException { WorldMapSegment segment = world.maps.worldMapSegments.get(segmentName); - HashSet displayedMapNames = new HashSet(); + Collection displayedMapNames = new HashSet(); Coord offsetWorldmapTo = new Coord(999999, 999999); for (WorldMapSegmentMap map : segment.maps.values()) { if (!shouldDisplayMapOnWorldmap(map.mapName)) continue; @@ -178,8 +179,8 @@ public final class WorldMapController { } Coord bottomRight = new Coord(0, 0); - - StringBuffer mapsAsHtml = new StringBuffer(); + + StringBuilder mapsAsHtml = new StringBuilder(1000); for (WorldMapSegmentMap segmentMap : segment.maps.values()) { File f = WorldMapController.getFileForMap(segmentMap.mapName); if (!f.exists()) continue; @@ -199,7 +200,7 @@ public final class WorldMapController { .append("px; top:") .append((segmentMap.worldPosition.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE) .append("px;\" />"); - if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) mapsAsHtml.append("\n"); + if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) mapsAsHtml.append('\n'); bottomRight.x = Math.max(bottomRight.x, segmentMap.worldPosition.x + size.width); bottomRight.y = Math.max(bottomRight.y, segmentMap.worldPosition.y + size.height); @@ -208,8 +209,8 @@ public final class WorldMapController { (bottomRight.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE ,(bottomRight.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE ); - - StringBuffer namedAreasAsHtml = new StringBuffer(); + + StringBuilder namedAreasAsHtml = new StringBuilder(500); for (NamedWorldMapArea area : segment.namedAreas.values()) { CoordRect r = determineNamedAreaBoundary(area, segment, world, displayedMapNames); if (r == null) continue; @@ -227,7 +228,7 @@ public final class WorldMapController { .append("px;\">") .append(area.name) .append(""); - if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) namedAreasAsHtml.append("\n"); + if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) namedAreasAsHtml.append('\n'); } return res.getString(R.string.worldmap_template) @@ -243,7 +244,7 @@ public final class WorldMapController { return world.maps.findPredefinedMap(map.mapName).size; } - private static CoordRect determineNamedAreaBoundary(NamedWorldMapArea area, WorldMapSegment segment, WorldContext world, HashSet displayedMapNames) { + private static CoordRect determineNamedAreaBoundary(NamedWorldMapArea area, WorldMapSegment segment, WorldContext world, Collection displayedMapNames) { Coord topLeft = null; Coord bottomRight = null; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatActionListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatActionListener.java new file mode 100644 index 000000000..dadc26ef2 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatActionListener.java @@ -0,0 +1,15 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.model.AttackResult; +import com.gpl.rpg.AndorsTrail.model.actor.Monster; + +public interface CombatActionListener { + void onPlayerAttackMissed(Monster target, AttackResult attackResult); + void onPlayerAttackSuccess(Monster target, AttackResult attackResult); + void onMonsterAttackMissed(Monster attacker, AttackResult attackResult); + void onMonsterAttackSuccess(Monster attacker, AttackResult attackResult); + void onPlayerKilledMonster(Monster target); + void onPlayerStartedFleeing(); + void onPlayerFailedFleeing(); + void onPlayerDoesNotHaveEnoughAP(); +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatActionListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatActionListeners.java new file mode 100644 index 000000000..86e150c75 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatActionListeners.java @@ -0,0 +1,80 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.model.AttackResult; +import com.gpl.rpg.AndorsTrail.model.actor.Monster; +import com.gpl.rpg.AndorsTrail.util.ListOfListeners; + +public final class CombatActionListeners extends ListOfListeners implements CombatActionListener { + + private final Function2 onPlayerAttackMissed = new Function2() { + @Override public void call(CombatActionListener listener, Monster target, AttackResult attackResult) { listener.onPlayerAttackMissed(target, attackResult); } + }; + + private final Function2 onPlayerAttackSuccess = new Function2() { + @Override public void call(CombatActionListener listener, Monster target, AttackResult attackResult) { listener.onPlayerAttackSuccess(target, attackResult); } + }; + + private final Function2 onMonsterAttackMissed = new Function2() { + @Override public void call(CombatActionListener listener, Monster attacker, AttackResult attackResult) { listener.onMonsterAttackMissed(attacker, attackResult); } + }; + + private final Function2 onMonsterAttackSuccess = new Function2() { + @Override public void call(CombatActionListener listener, Monster attacker, AttackResult attackResult) { listener.onMonsterAttackSuccess(attacker, attackResult); } + }; + + private final Function1 onPlayerKilledMonster = new Function1() { + @Override public void call(CombatActionListener listener, Monster target) { listener.onPlayerKilledMonster(target); } + }; + + private final Function onPlayerStartedFleeing = new Function() { + @Override public void call(CombatActionListener listener) { listener.onPlayerStartedFleeing(); } + }; + + private final Function onPlayerFailedFleeing = new Function() { + @Override public void call(CombatActionListener listener) { listener.onPlayerFailedFleeing(); } + }; + + private final Function onPlayerDoesNotHaveEnoughAP = new Function() { + @Override public void call(CombatActionListener listener) { listener.onPlayerDoesNotHaveEnoughAP(); } + }; + + @Override + public void onPlayerAttackMissed(Monster target, AttackResult attackResult) { + callAllListeners(this.onPlayerAttackMissed, target, attackResult); + } + + @Override + public void onPlayerAttackSuccess(Monster target, AttackResult attackResult) { + callAllListeners(this.onPlayerAttackSuccess, target, attackResult); + } + + @Override + public void onMonsterAttackMissed(Monster attacker, AttackResult attackResult) { + callAllListeners(this.onMonsterAttackMissed, attacker, attackResult); + } + + @Override + public void onMonsterAttackSuccess(Monster attacker, AttackResult attackResult) { + callAllListeners(this.onMonsterAttackSuccess, attacker, attackResult); + } + + @Override + public void onPlayerKilledMonster(Monster target) { + callAllListeners(this.onPlayerKilledMonster, target); + } + + @Override + public void onPlayerStartedFleeing() { + callAllListeners(this.onPlayerStartedFleeing); + } + + @Override + public void onPlayerFailedFleeing() { + callAllListeners(this.onPlayerFailedFleeing); + } + + @Override + public void onPlayerDoesNotHaveEnoughAP() { + callAllListeners(this.onPlayerDoesNotHaveEnoughAP); + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatSelectionListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatSelectionListener.java new file mode 100644 index 000000000..740ce25af --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatSelectionListener.java @@ -0,0 +1,10 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.model.actor.Monster; +import com.gpl.rpg.AndorsTrail.util.Coord; + +public interface CombatSelectionListener { + void onMonsterSelected(Monster m, Coord selectedPosition, Coord previousSelection); + void onMovementDestinationSelected(Coord selectedPosition, Coord previousSelection); + void onCombatSelectionCleared(Coord previousSelection); +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatSelectionListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatSelectionListeners.java new file mode 100644 index 000000000..caf2574e2 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatSelectionListeners.java @@ -0,0 +1,35 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.model.actor.Monster; +import com.gpl.rpg.AndorsTrail.util.ListOfListeners; +import com.gpl.rpg.AndorsTrail.util.Coord; + +public final class CombatSelectionListeners extends ListOfListeners implements CombatSelectionListener { + + private final Function3 onMonsterSelected = new Function3() { + @Override public void call(CombatSelectionListener listener, Monster monster, Coord selectedPosition, Coord previousSelection) { listener.onMonsterSelected(monster, selectedPosition, previousSelection); } + }; + + private final Function2 onMovementDestinationSelected = new Function2() { + @Override public void call(CombatSelectionListener listener, Coord selectedPosition, Coord previousSelection) { listener.onMovementDestinationSelected(selectedPosition, previousSelection); } + }; + + private final Function1 onCombatSelectionCleared = new Function1() { + @Override public void call(CombatSelectionListener listener, Coord previousSelection) { listener.onCombatSelectionCleared(previousSelection); } + }; + + @Override + public void onMonsterSelected(Monster m, Coord selectedPosition, Coord previousSelection) { + callAllListeners(this.onMonsterSelected, m, selectedPosition, previousSelection); + } + + @Override + public void onMovementDestinationSelected(Coord selectedPosition, Coord previousSelection) { + callAllListeners(this.onMovementDestinationSelected, selectedPosition, previousSelection); + } + + @Override + public void onCombatSelectionCleared(Coord previousSelection) { + callAllListeners(this.onCombatSelectionCleared, previousSelection); + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatTurnListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatTurnListener.java new file mode 100644 index 000000000..a24964184 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatTurnListener.java @@ -0,0 +1,10 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.model.actor.Monster; + +public interface CombatTurnListener { + void onCombatStarted(); + void onCombatEnded(); + void onNewPlayerTurn(); + void onMonsterIsAttacking(Monster m); +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatTurnListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatTurnListeners.java new file mode 100644 index 000000000..91f8f84df --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/CombatTurnListeners.java @@ -0,0 +1,43 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.model.actor.Monster; +import com.gpl.rpg.AndorsTrail.util.ListOfListeners; + +public final class CombatTurnListeners extends ListOfListeners implements CombatTurnListener { + + private final Function onCombatStarted = new Function() { + @Override public void call(CombatTurnListener listener) { listener.onCombatStarted(); } + }; + + private final Function onCombatEnded = new Function() { + @Override public void call(CombatTurnListener listener) { listener.onCombatEnded(); } + }; + + private final Function onNewPlayerTurn = new Function() { + @Override public void call(CombatTurnListener listener) { listener.onNewPlayerTurn(); } + }; + + private final Function1 onMonsterIsAttacking = new Function1() { + @Override public void call(CombatTurnListener listener, Monster m) { listener.onMonsterIsAttacking(m); } + }; + + @Override + public void onCombatStarted() { + callAllListeners(this.onCombatStarted); + } + + @Override + public void onCombatEnded() { + callAllListeners(this.onCombatEnded); + } + + @Override + public void onNewPlayerTurn() { + callAllListeners(this.onNewPlayerTurn); + } + + @Override + public void onMonsterIsAttacking(Monster m) { + callAllListeners(this.onMonsterIsAttacking, m); + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/GameRoundListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/GameRoundListener.java new file mode 100644 index 000000000..de8161e3a --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/GameRoundListener.java @@ -0,0 +1,7 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +public interface GameRoundListener { + void onNewTick(); + void onNewRound(); + void onNewFullRound(); +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/GameRoundListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/GameRoundListeners.java new file mode 100644 index 000000000..3804a479a --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/GameRoundListeners.java @@ -0,0 +1,33 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.util.ListOfListeners; + +public final class GameRoundListeners extends ListOfListeners implements GameRoundListener { + + private final Function onNewTick = new Function() { + @Override public void call(GameRoundListener listener) { listener.onNewTick(); } + }; + + private final Function onNewRound = new Function() { + @Override public void call(GameRoundListener listener) { listener.onNewRound(); } + }; + + private final Function onNewFullRound = new Function() { + @Override public void call(GameRoundListener listener) { listener.onNewFullRound(); } + }; + + @Override + public void onNewTick() { + callAllListeners(this.onNewTick); + } + + @Override + public void onNewRound() { + callAllListeners(this.onNewRound); + } + + @Override + public void onNewFullRound() { + callAllListeners(this.onNewFullRound); + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/LootBagListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/LootBagListener.java new file mode 100644 index 000000000..816c9129e --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/LootBagListener.java @@ -0,0 +1,9 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; +import com.gpl.rpg.AndorsTrail.util.Coord; + +public interface LootBagListener { + void onLootBagCreated(PredefinedMap map, Coord p); + void onLootBagRemoved(PredefinedMap map, Coord p); +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/LootBagListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/LootBagListeners.java new file mode 100644 index 000000000..440908eac --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/LootBagListeners.java @@ -0,0 +1,26 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.util.ListOfListeners; +import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; +import com.gpl.rpg.AndorsTrail.util.Coord; + +public final class LootBagListeners extends ListOfListeners implements LootBagListener { + + private final Function2 onLootBagCreated = new Function2() { + @Override public void call(LootBagListener listener, PredefinedMap map, Coord p) { listener.onLootBagCreated(map, p); } + }; + + private final Function2 onLootBagRemoved = new Function2() { + @Override public void call(LootBagListener listener, PredefinedMap map, Coord p) { listener.onLootBagRemoved(map, p); } + }; + + @Override + public void onLootBagCreated(PredefinedMap map, Coord p) { + callAllListeners(this.onLootBagCreated, map, p); + } + + @Override + public void onLootBagRemoved(PredefinedMap map, Coord p) { + callAllListeners(this.onLootBagRemoved, map, p); + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/MonsterMovementListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/MonsterMovementListener.java new file mode 100644 index 000000000..48d7173f7 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/MonsterMovementListener.java @@ -0,0 +1,10 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.model.actor.Monster; +import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; +import com.gpl.rpg.AndorsTrail.util.CoordRect; + +public interface MonsterMovementListener { + void onMonsterSteppedOnPlayer(Monster m); + void onMonsterMoved(PredefinedMap map, Monster m, CoordRect previousPosition); +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/MonsterMovementListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/MonsterMovementListeners.java new file mode 100644 index 000000000..a7259b1fa --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/MonsterMovementListeners.java @@ -0,0 +1,27 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.model.actor.Monster; +import com.gpl.rpg.AndorsTrail.util.ListOfListeners; +import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; +import com.gpl.rpg.AndorsTrail.util.CoordRect; + +public final class MonsterMovementListeners extends ListOfListeners implements MonsterMovementListener { + + private final Function1 onMonsterSteppedOnPlayer = new Function1() { + @Override public void call(MonsterMovementListener listener, Monster monster) { listener.onMonsterSteppedOnPlayer(monster); } + }; + + private final Function3 onMonsterMoved = new Function3() { + @Override public void call(MonsterMovementListener listener, PredefinedMap map, Monster monster, CoordRect previousPosition) { listener.onMonsterMoved(map, monster, previousPosition); } + }; + + @Override + public void onMonsterSteppedOnPlayer(Monster m) { + callAllListeners(this.onMonsterSteppedOnPlayer, m); + } + + @Override + public void onMonsterMoved(PredefinedMap map, Monster m, CoordRect previousPosition) { + callAllListeners(this.onMonsterMoved, map, m, previousPosition); + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/MonsterSpawnListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/MonsterSpawnListener.java new file mode 100644 index 000000000..5892af823 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/MonsterSpawnListener.java @@ -0,0 +1,14 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.model.actor.Monster; +import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; +import com.gpl.rpg.AndorsTrail.util.Coord; +import com.gpl.rpg.AndorsTrail.util.CoordRect; + +public interface MonsterSpawnListener { + void onMonsterSpawned(PredefinedMap map, Monster m); + void onMonsterRemoved(PredefinedMap map, Monster m, CoordRect previousPosition); + void onSplatterAdded(PredefinedMap map, Coord p); + void onSplatterChanged(PredefinedMap map, Coord p); + void onSplatterRemoved(PredefinedMap map, Coord p); +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/MonsterSpawnListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/MonsterSpawnListeners.java new file mode 100644 index 000000000..0c15ca3f5 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/MonsterSpawnListeners.java @@ -0,0 +1,55 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.model.actor.Monster; +import com.gpl.rpg.AndorsTrail.util.ListOfListeners; +import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; +import com.gpl.rpg.AndorsTrail.util.Coord; +import com.gpl.rpg.AndorsTrail.util.CoordRect; + +public final class MonsterSpawnListeners extends ListOfListeners implements MonsterSpawnListener { + + private final Function2 onMonsterSpawned = new Function2() { + @Override public void call(MonsterSpawnListener listener, PredefinedMap map, Monster monster) { listener.onMonsterSpawned(map, monster); } + }; + + private final Function3 onMonsterRemoved = new Function3() { + @Override public void call(MonsterSpawnListener listener, PredefinedMap map, Monster monster, CoordRect previousPosition) { listener.onMonsterRemoved(map, monster, previousPosition); } + }; + + private final Function2 onSplatterAdded = new Function2() { + @Override public void call(MonsterSpawnListener listener, PredefinedMap map, Coord p) { listener.onSplatterAdded(map, p); } + }; + + private final Function2 onSplatterChanged = new Function2() { + @Override public void call(MonsterSpawnListener listener, PredefinedMap map, Coord p) { listener.onSplatterChanged(map, p); } + }; + + private final Function2 onSplatterRemoved = new Function2() { + @Override public void call(MonsterSpawnListener listener, PredefinedMap map, Coord p) { listener.onSplatterRemoved(map, p); } + }; + + @Override + public void onMonsterSpawned(PredefinedMap map, Monster m) { + callAllListeners(this.onMonsterSpawned, map, m); + } + + @Override + public void onMonsterRemoved(PredefinedMap map, Monster m, CoordRect previousPosition) { + callAllListeners(this.onMonsterRemoved, map, m, previousPosition); + } + + @Override + public void onSplatterAdded(PredefinedMap map, Coord p) { + callAllListeners(this.onSplatterAdded, map, p); + } + + @Override + public void onSplatterChanged(PredefinedMap map, Coord p) { + callAllListeners(this.onSplatterChanged, map, p); + } + + @Override + public void onSplatterRemoved(PredefinedMap map, Coord p) { + callAllListeners(this.onSplatterRemoved, map, p); + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/PlayerMovementListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/PlayerMovementListener.java new file mode 100644 index 000000000..ffa475d5d --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/PlayerMovementListener.java @@ -0,0 +1,9 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; +import com.gpl.rpg.AndorsTrail.util.Coord; + +public interface PlayerMovementListener { + void onPlayerMoved(Coord newPosition, Coord previousPosition); + void onPlayerEnteredNewMap(PredefinedMap map, Coord p); +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/PlayerMovementListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/PlayerMovementListeners.java new file mode 100644 index 000000000..3a03dc34e --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/PlayerMovementListeners.java @@ -0,0 +1,26 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.util.ListOfListeners; +import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; +import com.gpl.rpg.AndorsTrail.util.Coord; + +public final class PlayerMovementListeners extends ListOfListeners implements PlayerMovementListener { + + private final Function2 onPlayerMoved = new Function2() { + @Override public void call(PlayerMovementListener listener, Coord newPosition, Coord previousPosition) { listener.onPlayerMoved(newPosition, previousPosition); } + }; + + private final Function2 onPlayerEnteredNewMap = new Function2() { + @Override public void call(PlayerMovementListener listener, PredefinedMap map, Coord p) { listener.onPlayerEnteredNewMap(map, p); } + }; + + @Override + public void onPlayerMoved(Coord newPosition, Coord previousPosition) { + callAllListeners(this.onPlayerMoved, newPosition, previousPosition); + } + + @Override + public void onPlayerEnteredNewMap(PredefinedMap map, Coord p) { + callAllListeners(this.onPlayerEnteredNewMap, map, p); + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/QuickSlotListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/QuickSlotListener.java new file mode 100644 index 000000000..0ce5b14e4 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/QuickSlotListener.java @@ -0,0 +1,6 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +public interface QuickSlotListener { + void onQuickSlotChanged(int slotId); + void onQuickSlotUsed(int slotId); +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/QuickSlotListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/QuickSlotListeners.java new file mode 100644 index 000000000..19b2d2793 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/QuickSlotListeners.java @@ -0,0 +1,24 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.util.ListOfListeners; + +public final class QuickSlotListeners extends ListOfListeners implements QuickSlotListener { + + private final Function1 onQuickSlotChanged = new Function1() { + @Override public void call(QuickSlotListener listener, Integer slotId) { listener.onQuickSlotChanged(slotId); } + }; + + private final Function1 onQuickSlotUsed = new Function1() { + @Override public void call(QuickSlotListener listener, Integer slotId) { listener.onQuickSlotUsed(slotId); } + }; + + @Override + public void onQuickSlotChanged(int slotId) { + callAllListeners(this.onQuickSlotChanged, slotId); + } + + @Override + public void onQuickSlotUsed(int slotId) { + callAllListeners(this.onQuickSlotUsed, slotId); + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListener.java new file mode 100644 index 000000000..4fb6a7d96 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListener.java @@ -0,0 +1,8 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.VisualEffectAnimation; + +public interface VisualEffectFrameListener { + void onNewAnimationFrame(VisualEffectAnimation animation, int tileID, int textYOffset); + void onAnimationCompleted(VisualEffectAnimation animation); +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListeners.java new file mode 100644 index 000000000..0801938c7 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/VisualEffectFrameListeners.java @@ -0,0 +1,25 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.VisualEffectAnimation; +import com.gpl.rpg.AndorsTrail.util.ListOfListeners; + +public final class VisualEffectFrameListeners extends ListOfListeners implements VisualEffectFrameListener { + + private final Function3 onNewAnimationFrame = new Function3() { + @Override public void call(VisualEffectFrameListener listener, VisualEffectAnimation animation, Integer tileID, Integer textYOffset) { listener.onNewAnimationFrame(animation, tileID, textYOffset); } + }; + + private final Function1 onAnimationCompleted = new Function1() { + @Override public void call(VisualEffectFrameListener listener, VisualEffectAnimation animation) { listener.onAnimationCompleted(animation); } + }; + + @Override + public void onNewAnimationFrame(VisualEffectAnimation animation, int tileID, int textYOffset) { + callAllListeners(this.onNewAnimationFrame, animation, tileID, textYOffset); + } + + @Override + public void onAnimationCompleted(VisualEffectAnimation animation) { + callAllListeners(this.onAnimationCompleted, animation); + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/WorldEventListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/WorldEventListener.java new file mode 100644 index 000000000..f91c6db98 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/WorldEventListener.java @@ -0,0 +1,21 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.model.actor.Monster; +import com.gpl.rpg.AndorsTrail.model.item.Loot; +import com.gpl.rpg.AndorsTrail.model.map.MapObject; + +import java.util.Collection; + +public interface WorldEventListener { + void onPlayerStartedConversation(Monster m, String phraseID); + void onPlayerSteppedOnMonster(Monster m); + void onPlayerSteppedOnMapSignArea(MapObject area); + void onPlayerSteppedOnKeyArea(MapObject area); + void onPlayerSteppedOnRestArea(MapObject area); + void onPlayerSteppedOnGroundLoot(Loot loot); + void onPlayerPickedUpGroundLoot(Loot loot); + void onPlayerFoundMonsterLoot(Collection loot, int exp); + void onPlayerPickedUpMonsterLoot(Collection loot, int exp); + void onPlayerRested(); + void onPlayerDied(int lostExp); +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/WorldEventListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/WorldEventListeners.java new file mode 100644 index 000000000..06fc98e0c --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/listeners/WorldEventListeners.java @@ -0,0 +1,110 @@ +package com.gpl.rpg.AndorsTrail.controller.listeners; + +import com.gpl.rpg.AndorsTrail.model.actor.Monster; +import com.gpl.rpg.AndorsTrail.model.item.Loot; +import com.gpl.rpg.AndorsTrail.util.ListOfListeners; +import com.gpl.rpg.AndorsTrail.model.map.MapObject; + +import java.util.Collection; + +public final class WorldEventListeners extends ListOfListeners implements WorldEventListener { + + private final Function2 onPlayerStartedConversation = new Function2() { + @Override public void call(WorldEventListener listener, Monster m, String phraseID) { listener.onPlayerStartedConversation(m, phraseID); } + }; + + private final Function1 onPlayerSteppedOnMonster = new Function1() { + @Override public void call(WorldEventListener listener, Monster m) { listener.onPlayerSteppedOnMonster(m); } + }; + + private final Function1 onPlayerSteppedOnMapSignArea = new Function1() { + @Override public void call(WorldEventListener listener, MapObject area) { listener.onPlayerSteppedOnMapSignArea(area); } + }; + + private final Function1 onPlayerSteppedOnKeyArea = new Function1() { + @Override public void call(WorldEventListener listener, MapObject area) { listener.onPlayerSteppedOnKeyArea(area); } + }; + + private final Function1 onPlayerSteppedOnRestArea = new Function1() { + @Override public void call(WorldEventListener listener, MapObject area) { listener.onPlayerSteppedOnRestArea(area); } + }; + + private final Function1 onPlayerSteppedOnGroundLoot = new Function1() { + @Override public void call(WorldEventListener listener, Loot loot) { listener.onPlayerSteppedOnGroundLoot(loot); } + }; + + private final Function1 onPlayerPickedUpGroundLoot = new Function1() { + @Override public void call(WorldEventListener listener, Loot loot) { listener.onPlayerPickedUpGroundLoot(loot); } + }; + + private final Function2, Integer> onPlayerFoundMonsterLoot = new Function2, Integer>() { + @Override public void call(WorldEventListener listener, Collection loot, Integer exp) { listener.onPlayerFoundMonsterLoot(loot, exp); } + }; + + private final Function2, Integer> onPlayerPickedUpMonsterLoot = new Function2, Integer>() { + @Override public void call(WorldEventListener listener, Collection loot, Integer exp) { listener.onPlayerPickedUpMonsterLoot(loot, exp); } + }; + + private final Function onPlayerRested = new Function() { + @Override public void call(WorldEventListener listener) { listener.onPlayerRested(); } + }; + + private final Function1 onPlayerDied = new Function1() { + @Override public void call(WorldEventListener listener, Integer lostExp) { listener.onPlayerDied(lostExp); } + }; + + @Override + public void onPlayerStartedConversation(Monster m, String phraseID) { + callAllListeners(this.onPlayerStartedConversation, m, phraseID); + } + + @Override + public void onPlayerSteppedOnMonster(Monster m) { + callAllListeners(this.onPlayerSteppedOnMonster, m); + } + + @Override + public void onPlayerSteppedOnMapSignArea(MapObject area) { + callAllListeners(this.onPlayerSteppedOnMapSignArea, area); + } + + @Override + public void onPlayerSteppedOnKeyArea(MapObject area) { + callAllListeners(this.onPlayerSteppedOnKeyArea, area); + } + + @Override + public void onPlayerSteppedOnRestArea(MapObject area) { + callAllListeners(this.onPlayerSteppedOnRestArea, area); + } + + @Override + public void onPlayerSteppedOnGroundLoot(Loot loot) { + callAllListeners(this.onPlayerSteppedOnGroundLoot, loot); + } + + @Override + public void onPlayerPickedUpGroundLoot(Loot loot) { + callAllListeners(this.onPlayerPickedUpGroundLoot, loot); + } + + @Override + public void onPlayerFoundMonsterLoot(Collection loot, int exp) { + callAllListeners(this.onPlayerFoundMonsterLoot, loot, exp); + } + + @Override + public void onPlayerPickedUpMonsterLoot(Collection loot, int exp) { + callAllListeners(this.onPlayerPickedUpMonsterLoot, loot, exp); + } + + @Override + public void onPlayerRested() { + callAllListeners(this.onPlayerRested); + } + + @Override + public void onPlayerDied(int lostExp) { + callAllListeners(this.onPlayerDied, lostExp); + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ModelContainer.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ModelContainer.java index 351c8ae36..58d6ab4a8 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ModelContainer.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ModelContainer.java @@ -4,6 +4,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import com.gpl.rpg.AndorsTrail.context.ViewContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; import com.gpl.rpg.AndorsTrail.model.actor.Player; import com.gpl.rpg.AndorsTrail.model.map.LayeredTileMap; @@ -25,8 +26,8 @@ public final class ModelContainer { // ====== PARCELABLE =================================================================== - public ModelContainer(DataInputStream src, WorldContext world, int fileversion) throws IOException { - this.player = Player.readFromParcel(src, world, fileversion); + public ModelContainer(DataInputStream src, WorldContext world, ViewContext view, int fileversion) throws IOException { + this.player = Player.readFromParcel(src, world, view, fileversion); this.currentMap = world.maps.findPredefinedMap(src.readUTF()); this.uiSelections = new InterfaceData(src, world, fileversion); if (uiSelections.selectedPosition != null) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/ActorCondition.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/ActorCondition.java index bb0848e6f..3f76fcd17 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/ActorCondition.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/ActorCondition.java @@ -6,7 +6,7 @@ import java.io.IOException; import com.gpl.rpg.AndorsTrail.context.WorldContext; -public class ActorCondition { +public final class ActorCondition { public static final int MAGNITUDE_REMOVE_ALL = -99; public static final int DURATION_FOREVER = 999; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/ActorConditionTypeCollection.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/ActorConditionTypeCollection.java index 92793fc78..e69b55efb 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/ActorConditionTypeCollection.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/ActorConditionTypeCollection.java @@ -6,7 +6,7 @@ import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.resource.parsers.ActorConditionsTypeParser; import com.gpl.rpg.AndorsTrail.util.L; -public class ActorConditionTypeCollection { +public final class ActorConditionTypeCollection { private final HashMap conditionTypes = new HashMap(); public ActorConditionType getActorConditionType(String conditionTypeID) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/SkillInfo.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/SkillInfo.java index ec4cc8800..90fd1ae4f 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/SkillInfo.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/SkillInfo.java @@ -2,7 +2,7 @@ package com.gpl.rpg.AndorsTrail.model.ability; import com.gpl.rpg.AndorsTrail.model.actor.Player; -public class SkillInfo { +public final class SkillInfo { public static final int MAXLEVEL_NONE = -1; public static final int LEVELUP_TYPE_ALWAYS_SHOWN = 0; public static final int LEVELUP_TYPE_ONLY_BY_QUESTS = 1; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/traits/AbilityModifierTraits.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/traits/AbilityModifierTraits.java index 354c19e94..115e6681c 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/traits/AbilityModifierTraits.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/traits/AbilityModifierTraits.java @@ -46,12 +46,6 @@ public final class AbilityModifierTraits { this.increaseDamageResistance = increaseDamageResistance; } - public boolean hasAttackChanceEffect() { return increaseAttackChance != 0; } - public boolean hasAttackDamageEffect() { return increaseMinDamage != 0 || increaseMaxDamage != 0; } - public boolean hasBlockEffect() { return increaseBlockChance != 0; } - public boolean hasCriticalSkillEffect() { return increaseCriticalSkill != 0; } - public boolean hasCriticalMultiplierEffect() { return setCriticalMultiplier != 0 && setCriticalMultiplier != 1; } - public int calculateCost(boolean isWeapon) { final int costBC = (int) (3*Math.pow(Math.max(0, increaseBlockChance), 2.5) + 28*increaseBlockChance); final int costAC = (int) (0.4*Math.pow(Math.max(0,increaseAttackChance), 2.5) - 6*Math.pow(Math.abs(Math.min(0,increaseAttackChance)),2.7)); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/traits/StatsModifierTraits.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/traits/StatsModifierTraits.java index 136661b89..833e58108 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/traits/StatsModifierTraits.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/traits/StatsModifierTraits.java @@ -2,7 +2,7 @@ package com.gpl.rpg.AndorsTrail.model.ability.traits; import com.gpl.rpg.AndorsTrail.util.ConstRange; -public class StatsModifierTraits { +public final class StatsModifierTraits { public static final int VISUAL_EFFECT_NONE = -1; public final int visualEffectID; public final ConstRange currentHPBoost; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Actor.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Actor.java index ee39db03c..25e06f50d 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Actor.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Actor.java @@ -8,7 +8,6 @@ import android.util.FloatMath; 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; @@ -27,7 +26,6 @@ public class Actor { public final Range ap = new Range(); public final Range health = new Range(); public final ArrayList conditions = new ArrayList(); - public final ActorConditionListeners conditionListener = new ActorConditionListeners(); public int moveCost; public int attackCost; public int attackChance; @@ -47,7 +45,9 @@ public class Actor { public boolean isImmuneToCriticalHits() { return isImmuneToCriticalHits; } public String getName() { return name; } + public int getCurrentAP() { return ap.current; } public int getMaxAP() { return ap.max; } + public int getCurrentHP() { return health.current; } public int getMaxHP() { return health.max; } public int getMoveCost() { return moveCost; } public int getAttackCost() { return attackCost; } @@ -76,18 +76,7 @@ public class Actor { public boolean isDead() { return health.current <= 0; } - public void setMaxAP() { - ap.setMax(); - } - public void setMaxHP() { - health.setMax(); - } - public boolean useAPs(int cost) { - if (ap.current < cost) return false; - ap.subtract(cost, false); - return true; - } public boolean hasAPs(int cost) { return ap.current >= cost; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Monster.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Monster.java index dd690f385..ece742a52 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Monster.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Monster.java @@ -32,8 +32,8 @@ public final class Monster extends Actor { this.iconID = monsterType.iconID; this.nextPosition = new CoordRect(new Coord(), monsterType.tileSize); resetStatsToBaseTraits(); - setMaxAP(); - setMaxHP(); + this.ap.setMax(); + this.health.setMax(); } public void resetStatsToBaseTraits() { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java index 855636756..b299c9c63 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java @@ -11,8 +11,8 @@ import android.util.FloatMath; import android.util.SparseIntArray; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; +import com.gpl.rpg.AndorsTrail.context.ViewContext; 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.ActorCondition; import com.gpl.rpg.AndorsTrail.model.item.DropListCollection; @@ -48,13 +48,13 @@ public final class Player extends Actor { 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; + public final SparseIntArray skillLevels = new SparseIntArray(); public int availableSkillIncreases = 0; public int useItemCost; public int reequipCost; + public int totalExperience; - private int totalExperience; private final HashMap > questProgress = new HashMap >(); - private final SparseIntArray skillLevels = new SparseIntArray(); private String spawnMap; private String spawnPlace; private final HashMap alignments = new HashMap(); @@ -141,8 +141,6 @@ public final class Player extends Actor { this.spawnMap = "home"; this.spawnPlace = "rest"; } - - ActorStatsController.recalculatePlayerStats(this); } public boolean hasExactQuestProgress(QuestProgress progress) { return hasExactQuestProgress(progress.questID, progress.progress); } @@ -164,10 +162,6 @@ public final class Player extends Actor { int experienceRequiredToReachThisLevel = getRequiredExperience(level); levelExperience.set(getRequiredExperienceForNextLevel(level), totalExperience - experienceRequiredToReachThisLevel); } - public void addExperience(int v) { - totalExperience += v; - levelExperience.add(v, true); - } private static int getRequiredExperience(int currentLevel) { int v = 0; @@ -193,10 +187,6 @@ public final class Player extends Actor { public boolean hasSkill(int skillID) { return getSkillLevel(skillID) > 0; } - public void addSkillLevel(int skillID) { - skillLevels.put(skillID, skillLevels.get(skillID) + 1); - ActorStatsController.recalculatePlayerStats(this); - } public boolean nextLevelAddsNewSkillpoint() { return thisLevelAddsNewSkillpoint(level + 1); } @@ -231,6 +221,8 @@ public final class Player extends Actor { public int getAvailableSkillIncreases() { return availableSkillIncreases; } public int getLevel() { return level; } public int getTotalExperience() { return totalExperience; } + public int getCurrentLevelExperience() { return levelExperience.current; } + public int getMaxLevelExperience() { return levelExperience.max; } public int getGold() { return inventory.gold; } public String getSpawnMap() { return spawnMap; } public String getSpawnPlace() { return spawnPlace; } @@ -261,9 +253,9 @@ public final class Player extends Actor { // ====== PARCELABLE =================================================================== - public static Player readFromParcel(DataInputStream src, WorldContext world, int fileversion) throws IOException { + public static Player readFromParcel(DataInputStream src, WorldContext world, ViewContext view, int fileversion) throws IOException { Player player = new Player(src, world, fileversion); - LegacySavegameFormatReaderForPlayer.upgradeSavegame(player, world, fileversion); + LegacySavegameFormatReaderForPlayer.upgradeSavegame(player, world, view, fileversion); return player; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/item/Loot.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/item/Loot.java index 6951758af..31f26e3df 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/item/Loot.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/item/Loot.java @@ -37,7 +37,18 @@ public final class Loot { } public boolean hasItems() { return gold != 0 || !items.isEmpty(); + } + public boolean isContainer() { + return !isVisible; } + public static Loot combine(Iterable loot) { + Loot result = new Loot(); + for (Loot l : loot) { + result.add(l); + } + return result; + } + public void clear() { exp = 0; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorConditionListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorConditionListeners.java index 3ea927190..5bc5df40c 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorConditionListeners.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorConditionListeners.java @@ -2,8 +2,9 @@ package com.gpl.rpg.AndorsTrail.model.listeners; import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition; import com.gpl.rpg.AndorsTrail.model.actor.Actor; +import com.gpl.rpg.AndorsTrail.util.ListOfListeners; -public class ActorConditionListeners extends ListOfListeners implements ActorConditionListener { +public final class ActorConditionListeners extends ListOfListeners implements ActorConditionListener { private final Function2 onActorConditionAdded = new Function2() { @Override public void call(ActorConditionListener listener, Actor actor, ActorCondition condition) { listener.onActorConditionAdded(actor, condition); } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorStatsListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorStatsListener.java new file mode 100644 index 000000000..a1cc6befa --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorStatsListener.java @@ -0,0 +1,10 @@ +package com.gpl.rpg.AndorsTrail.model.listeners; + +import com.gpl.rpg.AndorsTrail.model.actor.Actor; + +public interface ActorStatsListener { + void onActorHealthChanged(Actor actor); + void onActorAPChanged(Actor actor); + void onActorAttackCostChanged(Actor actor, int newAttackCost); + void onActorMoveCostChanged(Actor actor, int newMoveCost); +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorStatsListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorStatsListeners.java new file mode 100644 index 000000000..cb8318005 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ActorStatsListeners.java @@ -0,0 +1,43 @@ +package com.gpl.rpg.AndorsTrail.model.listeners; + +import com.gpl.rpg.AndorsTrail.model.actor.Actor; +import com.gpl.rpg.AndorsTrail.util.ListOfListeners; + +public final class ActorStatsListeners extends ListOfListeners implements ActorStatsListener { + + private final Function1 onActorHealthChanged = new Function1() { + @Override public void call(ActorStatsListener listener, Actor actor) { listener.onActorHealthChanged(actor); } + }; + + private final Function1 onActorAPChanged = new Function1() { + @Override public void call(ActorStatsListener listener, Actor actor) { listener.onActorAPChanged(actor); } + }; + + private final Function2 onActorAttackCostChanged = new Function2() { + @Override public void call(ActorStatsListener listener, Actor actor, Integer newAttackCost) { listener.onActorAttackCostChanged(actor, newAttackCost); } + }; + + private final Function2 onActorMoveCostChanged = new Function2() { + @Override public void call(ActorStatsListener listener, Actor actor, Integer newMoveCost) { listener.onActorMoveCostChanged(actor, newMoveCost); } + }; + + @Override + public void onActorHealthChanged(Actor actor) { + callAllListeners(this.onActorHealthChanged, actor); + } + + @Override + public void onActorAPChanged(Actor actor) { + callAllListeners(this.onActorAPChanged, actor); + } + + @Override + public void onActorAttackCostChanged(Actor actor, int newAttackCost) { + callAllListeners(this.onActorAttackCostChanged, actor, newAttackCost); + } + + @Override + public void onActorMoveCostChanged(Actor actor, int newMoveCost) { + callAllListeners(this.onActorMoveCostChanged, actor, newMoveCost); + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/PlayerStatsListener.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/PlayerStatsListener.java new file mode 100644 index 000000000..49fd1ecb9 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/PlayerStatsListener.java @@ -0,0 +1,7 @@ +package com.gpl.rpg.AndorsTrail.model.listeners; + +import com.gpl.rpg.AndorsTrail.model.actor.Player; + +public interface PlayerStatsListener { + void onPlayerExperienceChanged(Player p); +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/PlayerStatsListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/PlayerStatsListeners.java new file mode 100644 index 000000000..99b09df2e --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/PlayerStatsListeners.java @@ -0,0 +1,16 @@ +package com.gpl.rpg.AndorsTrail.model.listeners; + +import com.gpl.rpg.AndorsTrail.model.actor.Player; +import com.gpl.rpg.AndorsTrail.util.ListOfListeners; + +public final class PlayerStatsListeners extends ListOfListeners implements PlayerStatsListener { + + private final Function1 onPlayerExperienceChanged = new Function1() { + @Override public void call(PlayerStatsListener listener, Player p) { listener.onPlayerExperienceChanged(p); } + }; + + @Override + public void onPlayerExperienceChanged(Player p) { + callAllListeners(this.onPlayerExperienceChanged, p); + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MapCollection.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MapCollection.java index 95a2dc4a8..8630417c2 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MapCollection.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MapCollection.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.HashMap; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; +import com.gpl.rpg.AndorsTrail.context.ViewContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; import com.gpl.rpg.AndorsTrail.util.L; @@ -42,12 +43,12 @@ public final class MapCollection { // ====== PARCELABLE =================================================================== - public void readFromParcel(DataInputStream src, WorldContext world, int fileversion) throws IOException { + public void readFromParcel(DataInputStream src, WorldContext world, ViewContext view, int fileversion) throws IOException { int size; if (fileversion == 5) size = 11; else size = src.readInt(); for(int i = 0; i < size; ++i) { - predefinedMaps.get(i).readFromParcel(src, world, fileversion); + predefinedMaps.get(i).readFromParcel(src, world, view, fileversion); if (i >= 40) { if (fileversion < 15) predefinedMaps.get(i).visited = false; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MonsterSpawnArea.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MonsterSpawnArea.java index e6a600c62..0d7100e59 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MonsterSpawnArea.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MonsterSpawnArea.java @@ -6,7 +6,6 @@ import java.io.IOException; import java.util.ArrayList; 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.actor.Monster; import com.gpl.rpg.AndorsTrail.model.actor.MonsterType; @@ -44,12 +43,6 @@ public final class MonsterSpawnArea { return null; } - public void healAllMonsters() { - for (Monster m : monsters) { - ActorStatsController.removeAllTemporaryConditions(m); - m.setMaxHP(); - } - } public void spawn(Coord p, WorldContext context) { final String monsterTypeID = monsterTypeIDs[Constants.rnd.nextInt(monsterTypeIDs.length)]; spawn(p, monsterTypeID, context); @@ -61,11 +54,12 @@ public final class MonsterSpawnArea { public void spawn(Coord p, String monsterTypeID, WorldContext context) { spawn(p, context.monsterTypes.getMonsterType(monsterTypeID)); } - public void spawn(Coord p, MonsterType type) { + public Monster spawn(Coord p, MonsterType type) { Monster m = new Monster(type); m.position.set(p); monsters.add(m); quantity.current++; + return m; } public void remove(Monster m) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/PredefinedMap.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/PredefinedMap.java index 50982e0ae..0a884d195 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/PredefinedMap.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/PredefinedMap.java @@ -6,11 +6,11 @@ import java.io.IOException; import java.util.ArrayList; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; +import com.gpl.rpg.AndorsTrail.context.ViewContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; import com.gpl.rpg.AndorsTrail.controller.Constants; import com.gpl.rpg.AndorsTrail.controller.VisualEffectController.BloodSplatter; import com.gpl.rpg.AndorsTrail.model.actor.Monster; -import com.gpl.rpg.AndorsTrail.model.actor.MonsterType; import com.gpl.rpg.AndorsTrail.model.item.ItemType; import com.gpl.rpg.AndorsTrail.model.item.Loot; import com.gpl.rpg.AndorsTrail.util.Coord; @@ -121,69 +121,6 @@ public final class PredefinedMap { return null; } - private boolean spawnInArea(MonsterSpawnArea a, WorldContext context, Coord playerPosition) { - return spawnInArea(a, a.getRandomMonsterType(context), playerPosition); - } - public boolean TEST_spawnInArea(MonsterSpawnArea a, MonsterType type) { return spawnInArea(a, type, null); } - private boolean spawnInArea(MonsterSpawnArea a, MonsterType type, Coord playerPosition) { - Coord p = getRandomFreePosition(a.area, type.tileSize, playerPosition); - if (p == null) return false; - a.spawn(p, type); - return true; - } - - public Coord getRandomFreePosition(CoordRect area, Size requiredSize, Coord playerPosition) { - CoordRect p = new CoordRect(requiredSize); - for(int i = 0; i < 100; ++i) { - p.topLeft.set( - area.topLeft.x + Constants.rnd.nextInt(area.size.width) - ,area.topLeft.y + Constants.rnd.nextInt(area.size.height)); - if (!monsterCanMoveTo(p)) continue; - if (playerPosition != null && p.contains(playerPosition)) continue; - return p.topLeft; - } - return null; // Couldn't find a free spot. - } - - public boolean monsterCanMoveTo(final CoordRect p) { - if (!isWalkable(p)) return false; - if (getMonsterAt(p) != null) return false; - MapObject m = getEventObjectAt(p.topLeft); - if (m != null) { - if (m.type == MapObject.MAPEVENT_NEWMAP) return false; - } - return true; - } - - public void spawnAll(WorldContext world) { - boolean respawnUniqueMonsters = false; - if (!visited) respawnUniqueMonsters = true; - for (MonsterSpawnArea a : spawnAreas) { - spawnAllInArea(world, a, respawnUniqueMonsters); - } - } - private void spawnAllInArea(WorldContext world, MonsterSpawnArea area, boolean respawnUniqueMonsters) { - while (area.isSpawnable(respawnUniqueMonsters)) { - final boolean wasAbleToSpawn = spawnInArea(area, world, null); - if (!wasAbleToSpawn) break; - } - area.healAllMonsters(); - } - public boolean maybeSpawn(WorldContext world) { - boolean hasSpawned = false; - for (MonsterSpawnArea a : spawnAreas) { - if (!a.isSpawnable(false)) continue; - if (!a.rollShouldSpawn()) continue; - if (spawnInArea(a, world, world.model.player.position)) hasSpawned = true; - } - return hasSpawned; - } - - public void remove(Monster m) { - for (MonsterSpawnArea a : spawnAreas) { - a.remove(m); - } - } public Loot getBagAt(final Coord p) { for (Loot l : groundBags) { if (l.position.equals(p)) return l; @@ -255,7 +192,7 @@ public final class PredefinedMap { // ====== PARCELABLE =================================================================== - public void readFromParcel(DataInputStream src, WorldContext world, int fileversion) throws IOException { + public void readFromParcel(DataInputStream src, WorldContext world, ViewContext view, int fileversion) throws IOException { final int loadedSpawnAreas = src.readInt(); for(int i = 0; i < loadedSpawnAreas; ++i) { this.spawnAreas[i].readFromParcel(src, world, fileversion); @@ -289,7 +226,7 @@ public final class PredefinedMap { for(int i = loadedSpawnAreas; i < spawnAreas.length; ++i) { MonsterSpawnArea area = this.spawnAreas[i]; - if (area.isUnique && visited) spawnAllInArea(world, area, true); + if (area.isUnique && visited) view.monsterSpawnController.spawnAllInArea(this, area, true); else area.reset(); } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceFileTokenizer.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceFileTokenizer.java index 0ad46bae4..a5570b7ff 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceFileTokenizer.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceFileTokenizer.java @@ -16,9 +16,9 @@ public class ResourceFileTokenizer { private static final String columnSeparator = "\\|"; private static final String fieldPattern = "([^\\|]*?|\\{\\s*\\{.*?\\}\\s*\\})" + columnSeparator; private static String repeat(String s, int count) { - String result = s; - for(int i = 1; i < count; ++i) result += s; - return result; + StringBuilder result = new StringBuilder(s); + for(int i = 1; i < count; ++i) result.append(s); + return result.toString(); } @@ -28,7 +28,7 @@ public class ResourceFileTokenizer { public ResourceFileTokenizer(int columns) { this.columns = columns; - this.pattern = Pattern.compile("^" + repeat(fieldPattern, columns) + "$", Pattern.MULTILINE | Pattern.DOTALL); + this.pattern = Pattern.compile('^' + repeat(fieldPattern, columns) + '$', Pattern.MULTILINE | Pattern.DOTALL); this.parts = new String[columns]; } @@ -39,7 +39,7 @@ public class ResourceFileTokenizer { } } - public Collection tokenizeRows(String input, HashMap dest, ResourceObjectParser> parser) { + public final Collection tokenizeRows(String input, HashMap dest, ResourceObjectParser> parser) { HashSet ids = new HashSet(); ArrayList> objects = new ArrayList>(); tokenizeRows(input, objects, parser); @@ -74,7 +74,7 @@ public class ResourceFileTokenizer { private static final Pattern outerPattern = Pattern.compile("^\\{(.*)\\}$", Pattern.MULTILINE | Pattern.DOTALL); private static final Pattern innerPattern = Pattern.compile("\\{(.*?)\\}", Pattern.MULTILINE | Pattern.DOTALL); - public void tokenizeArray(String input, ArrayList dest, ResourceObjectParser parser) { + public final void tokenizeArray(String input, ArrayList dest, ResourceObjectParser parser) { Matcher matcher = outerPattern.matcher(input); if (!matcher.find()) return; @@ -88,8 +88,8 @@ public class ResourceFileTokenizer { T parseRow(String[] parts); } - public static abstract class ResourceParserFor extends ResourceFileTokenizer implements ResourceObjectParser> { - public ResourceParserFor(int columns) { + public abstract static class ResourceParserFor extends ResourceFileTokenizer implements ResourceObjectParser> { + protected ResourceParserFor(int columns) { super(columns); } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileCollection.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileCollection.java index 67d80f192..3f5e3b9a8 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileCollection.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileCollection.java @@ -4,7 +4,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; -public class TileCollection { +public final class TileCollection { private final Bitmap[] bitmaps; public final int maxTileID; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileCutter.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileCutter.java index a076ea534..442191577 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileCutter.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileCutter.java @@ -5,7 +5,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; -public class TileCutter { +public final class TileCutter { private final ResourceFileTileset sourceFile; private final Bitmap tilesetImage; private boolean recycle = true; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForMonster.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForMonster.java index 73173759a..7e65e682b 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForMonster.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForMonster.java @@ -7,7 +7,7 @@ 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 final 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)); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForPlayer.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForPlayer.java index 00a1c9dc9..32a0cfea0 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForPlayer.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegameFormatReaderForPlayer.java @@ -5,8 +5,8 @@ import java.io.IOException; import android.util.FloatMath; +import com.gpl.rpg.AndorsTrail.context.ViewContext; 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; @@ -66,7 +66,7 @@ public final class LegacySavegameFormatReaderForPlayer { player.addQuestProgress(new QuestProgress(questID, progress)); } - public static void upgradeSavegame(Player player, WorldContext world, int fileversion) { + public static void upgradeSavegame(Player player, WorldContext world, ViewContext view, int fileversion) { if (fileversion <= 12) { player.useItemCost = 5; @@ -89,9 +89,9 @@ public final class LegacySavegameFormatReaderForPlayer { } if (fileversion <= 27) { - correctActorConditionsFromItemsPre0611b1(player, "bless", world, "elytharan_redeemer"); - correctActorConditionsFromItemsPre0611b1(player, "blackwater_misery", world, "bwm_dagger"); - correctActorConditionsFromItemsPre0611b1(player, "regen", world, "ring_shadow0"); + correctActorConditionsFromItemsPre0611b1(player, "bless", world, view, "elytharan_redeemer"); + correctActorConditionsFromItemsPre0611b1(player, "blackwater_misery", world, view, "bwm_dagger"); + correctActorConditionsFromItemsPre0611b1(player, "regen", world, view, "ring_shadow0"); } if (fileversion <= 30) { @@ -105,7 +105,7 @@ public final class LegacySavegameFormatReaderForPlayer { 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) { + private static void correctActorConditionsFromItemsPre0611b1(Player player, String conditionTypeID, WorldContext world, ViewContext view, String itemTypeIDWithCondition) { if (!player.hasCondition(conditionTypeID)) return; boolean hasItemWithCondition = false; for (ItemType t : player.inventory.wear) { @@ -120,7 +120,7 @@ public final class LegacySavegameFormatReaderForPlayer { } if (hasItemWithCondition) return; - ActorStatsController.removeConditionsFromUnequippedItem(player, world.itemTypes.getItemType(itemTypeIDWithCondition)); + view.actorStatsController.removeConditionsFromUnequippedItem(player, world.itemTypes.getItemType(itemTypeIDWithCondition)); } public static void readCombatTraitsPreV034(DataInputStream src, int fileversion) throws IOException { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/Savegames.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/Savegames.java new file mode 100644 index 000000000..ac9bbb033 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/Savegames.java @@ -0,0 +1,209 @@ +package com.gpl.rpg.AndorsTrail.savegames; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import android.content.Context; +import android.os.Environment; + +import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; +import com.gpl.rpg.AndorsTrail.context.ViewContext; +import com.gpl.rpg.AndorsTrail.context.WorldContext; +import com.gpl.rpg.AndorsTrail.controller.Constants; +import com.gpl.rpg.AndorsTrail.model.ModelContainer; +import com.gpl.rpg.AndorsTrail.util.L; + +public final class Savegames { + public static final int SLOT_QUICKSAVE = 0; + + public static final int LOAD_RESULT_SUCCESS = 0; + public static final int LOAD_RESULT_UNKNOWN_ERROR = 1; + public static final int LOAD_RESULT_FUTURE_VERSION = 2; + + public static boolean saveWorld(WorldContext world, Context androidContext, int slot, String displayInfo) { + try { + // Create the savegame in a temporary memorystream first to ensure that the savegame can + // be created correctly. We don't want to trash the user's file unneccessarily if there is an error. + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + saveWorld(world, bos, displayInfo); + byte[] savegame = bos.toByteArray(); + bos.close(); + + FileOutputStream fos = getOutputFile(androidContext, slot); + fos.write(savegame); + fos.close(); + return true; + } catch (IOException e) { + L.log("Error saving world: " + e.toString()); + return false; + } + } + public static int loadWorld(WorldContext world, ViewContext view, Context androidContext, int slot) { + try { + FileInputStream fos = getInputFile(androidContext, slot); + int result = loadWorld(world, view, fos); + fos.close(); + return result; + } catch (IOException e) { + if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) { + L.log("Error loading world: " + e.toString()); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + L.log("Load error: " + sw.toString()); + } + return LOAD_RESULT_UNKNOWN_ERROR; + } + } + + private static FileOutputStream getOutputFile(Context androidContext, int slot) throws IOException { + if (slot == SLOT_QUICKSAVE) { + return androidContext.openFileOutput(Constants.FILENAME_SAVEGAME_QUICKSAVE, Context.MODE_PRIVATE); + } else { + ensureSavegameDirectoryExists(); + return new FileOutputStream(getSlotFile(slot)); + } + } + private static void ensureSavegameDirectoryExists() { + File root = Environment.getExternalStorageDirectory(); + File dir = new File(root, Constants.FILENAME_SAVEGAME_DIRECTORY); + if (!dir.exists()) dir.mkdir(); + } + private static FileInputStream getInputFile(Context androidContext, int slot) throws IOException { + if (slot == SLOT_QUICKSAVE) { + return androidContext.openFileInput(Constants.FILENAME_SAVEGAME_QUICKSAVE); + } else { + return new FileInputStream(getSlotFile(slot)); + } + } + private static File getSlotFile(int slot) { + File root = getSavegameDirectory(); + return new File(root, Constants.FILENAME_SAVEGAME_FILENAME_PREFIX + slot); + } + + private static File getSavegameDirectory() { + File root = Environment.getExternalStorageDirectory(); + return new File(root, Constants.FILENAME_SAVEGAME_DIRECTORY); + } + + 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.getName(), displayInfo); + world.maps.writeToParcel(dest, flags); + world.model.writeToParcel(dest, flags); + dest.close(); + } + + public static int loadWorld(WorldContext world, ViewContext view, InputStream inState) throws IOException { + DataInputStream src = new DataInputStream(inState); + final FileHeader header = new FileHeader(src); + if (header.fileversion > AndorsTrailApplication.CURRENT_VERSION) return LOAD_RESULT_FUTURE_VERSION; + + world.maps.readFromParcel(src, world, view, header.fileversion); + world.model = new ModelContainer(src, world, view, header.fileversion); + src.close(); + + onWorldLoaded(world, view); + + return LOAD_RESULT_SUCCESS; + } + + private static void onWorldLoaded(WorldContext world, ViewContext view) { + view.actorStatsController.recalculatePlayerStats(world.model.player); + view.controller.resetMapsNotRecentlyVisited(); + view.movementController.moveBlockedActors(); + } + + public static FileHeader quickload(Context androidContext, int slot) { + try { + if (slot != SLOT_QUICKSAVE) { + File f = getSlotFile(slot); + if (!f.exists()) return null; + } + FileInputStream fos = getInputFile(androidContext, slot); + DataInputStream src = new DataInputStream(fos); + final FileHeader header = new FileHeader(src); + src.close(); + fos.close(); + return header; + } catch (Exception e) { + return null; + } + } + + private static final Pattern savegameFilenamePattern = Pattern.compile(Constants.FILENAME_SAVEGAME_FILENAME_PREFIX + "(\\d+)"); + public static List getUsedSavegameSlots(Context androidContext) { + try { + final List result = new ArrayList(); + getSavegameDirectory().listFiles(new FilenameFilter() { + @Override + public boolean accept(File f, String filename) { + Matcher m = savegameFilenamePattern.matcher(filename); + if (m != null && m.matches()) { + result.add(Integer.parseInt(m.group(1))); + return true; + } + return false; + } + }); + Collections.sort(result); + return result; + } catch (Exception e) { + return null; + } + } + + public static final class FileHeader { + public final int fileversion; + public final String playerName; + public final String displayInfo; + + public FileHeader(String playerName, String displayInfo) { + this.fileversion = AndorsTrailApplication.CURRENT_VERSION; + this.playerName = playerName; + this.displayInfo = displayInfo; + } + + public String describe() { + return playerName + ", " + displayInfo; + } + + + // ====== PARCELABLE =================================================================== + + public FileHeader(DataInputStream src) throws IOException { + int fileversion = src.readInt(); + if (fileversion == 11) fileversion = 5; // Fileversion 5 had no version identifier, but the first byte was 11. + this.fileversion = fileversion; + if (fileversion >= 14) { // Before fileversion 14 (0.6.7), we had no file header. + this.playerName = src.readUTF(); + this.displayInfo = src.readUTF(); + } else { + this.playerName = null; + this.displayInfo = null; + } + } + + public static void writeToParcel(DataOutputStream dest, String playerName, String displayInfo) throws IOException { + dest.writeInt(AndorsTrailApplication.CURRENT_VERSION); + dest.writeUTF(playerName); + dest.writeUTF(displayInfo); + } + } +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/Coord.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/Coord.java index 88178792a..f05f77783 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/Coord.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/Coord.java @@ -11,7 +11,7 @@ public final class Coord { public Coord(int x, int y) { this.x = x; this.y = y; } public Coord(Coord p) { this.x = p.x; this.y = p.y; } - public String toString() { return "(" + x + "," + y + ")"; } + public String toString() { return "(" + x + ',' + y + ')'; } public void set(int x, int y) { this.x = x; this.y = y; } public void set(Coord r) { this.x = r.x; @@ -26,8 +26,8 @@ public final class Coord { final int dx = x - p.x; final int dy = y - p.y; if (dx == 0 && dy == 0) return false; - else if (Math.abs(dx) > 1) return false; - else if (Math.abs(dy) > 1) return false; + if (Math.abs(dx) > 1) return false; + if (Math.abs(dy) > 1) return false; return true; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/CoordRect.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/CoordRect.java index f37de82e1..aa875e5a2 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/CoordRect.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/CoordRect.java @@ -17,17 +17,17 @@ public final class CoordRect { } public boolean contains(Coord p) { if (p.x < topLeft.x) return false; - else if (p.y < topLeft.y) return false; - else if (p.x - topLeft.x >= size.width) return false; - else if (p.y - topLeft.y >= size.height) return false; - else return true; + if (p.y < topLeft.y) return false; + if (p.x - topLeft.x >= size.width) return false; + if (p.y - topLeft.y >= size.height) return false; + return true; } public boolean contains(final int x, final int y) { if (x < topLeft.x) return false; - else if (y < topLeft.y) return false; - else if (x - topLeft.x >= size.width) return false; - else if (y - topLeft.y >= size.height) return false; - else return true; + if (y < topLeft.y) return false; + if (x - topLeft.x >= size.width) return false; + if (y - topLeft.y >= size.height) return false; + return true; } /* @@ -51,9 +51,9 @@ public final class CoordRect { final int dx = p.x - topLeft.x; final int dy = p.y - topLeft.y; if (dx < -1) return false; - else if (dy < -1) return false; - else if (dx > size.width) return false; - else if (dy > size.height) return false; + if (dy < -1) return false; + if (dx > size.width) return false; + if (dy > size.height) return false; return true; } public Coord findPositionAdjacentTo(Coord p) { @@ -69,6 +69,6 @@ public final class CoordRect { } public String toString() { - return "{" + topLeft.toString() + ", " + size.toString() + "}"; + return '{' + topLeft.toString() + ", " + size.toString() + '}'; } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/L.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/L.java index daed6c79f..e61f4df31 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/L.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/L.java @@ -4,7 +4,7 @@ import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import android.util.Log; -public class L { +public final class L { private static final String TAG = "AndorsTrail"; public static void log(String s) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ListOfListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/ListOfListeners.java similarity index 65% rename from AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ListOfListeners.java rename to AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/ListOfListeners.java index c968e3e46..dc1b89949 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/listeners/ListOfListeners.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/ListOfListeners.java @@ -1,4 +1,4 @@ -package com.gpl.rpg.AndorsTrail.model.listeners; +package com.gpl.rpg.AndorsTrail.util; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -8,7 +8,7 @@ import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; public class ListOfListeners { private final ArrayList> listeners = new ArrayList>(); - public void add(T listener) { + public final void add(T listener) { if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { for (WeakReference ref : listeners) { if (ref.get() == listener) { @@ -18,7 +18,7 @@ public class ListOfListeners { } listeners.add(new WeakReference(listener)); } - public void remove(T listenerToRemove) { + public final void remove(T listenerToRemove) { for (int i = listeners.size()-1; i >= 0; --i) { T listener = listeners.get(i).get(); if (listener == null || listener == listenerToRemove) { @@ -27,27 +27,34 @@ public class ListOfListeners { } } - protected void callAllListeners(Function e) { + protected final void callAllListeners(Function 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 void callAllListeners(Function1 e, Arg1 arg) { + protected final void callAllListeners(Function1 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 void callAllListeners(Function2 e, Arg1 arg1, Arg2 arg2) { + protected final void callAllListeners(Function2 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 final void callAllListeners(Function3 e, Arg1 arg1, Arg2 arg2, Arg3 arg3) { + 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, arg3); + } + } protected static interface Function { public void call(Listener listener); @@ -58,4 +65,7 @@ public class ListOfListeners { protected static interface Function2 { public void call(Listener listener, Arg1 arg1, Arg2 arg2); } + protected static interface Function3 { + public void call(Listener listener, Arg1 arg1, Arg2 arg2, Arg3 arg3); + } } \ No newline at end of file diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/LruCache.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/LruCache.java index a744c6bb7..8ddfabcdf 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/LruCache.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/LruCache.java @@ -26,7 +26,7 @@ import java.util.Map; * framework's implementation. See the framework SDK documentation for a class * overview. */ -public class LruCache { +public final class LruCache { private final LinkedHashMap map; /** Size of this cache in units. Not necessarily the number of elements. */ diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/Range.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/Range.java index 320c6fce6..4179bd846 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/Range.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/Range.java @@ -38,8 +38,12 @@ public final class Range { if (!mayOverflow) capAtMax(); return (this.current != valueBefore); } - public void capAtMax() { - if (current > max) current = max; + public boolean capAtMax() { + if (current > max) { + current = max; + return true; + } + return false; } public void addToMax(int value) { this.max += value; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/ActorConditionList.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/ActorConditionList.java index 367c27352..e10541278 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/ActorConditionList.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/ActorConditionList.java @@ -26,7 +26,7 @@ public final class ActorConditionList extends LinearLayout { setFocusable(false); setOrientation(LinearLayout.VERTICAL); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivityContext(context); - this.world = app.world; + this.world = app.getWorld(); } public void update(Iterable conditions) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/CombatView.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/CombatView.java index 5d1ecedd1..52eb9ae1e 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/CombatView.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/CombatView.java @@ -20,12 +20,15 @@ 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.CombatController; +import com.gpl.rpg.AndorsTrail.controller.listeners.CombatSelectionListener; +import com.gpl.rpg.AndorsTrail.controller.listeners.CombatTurnListener; +import com.gpl.rpg.AndorsTrail.model.actor.Actor; import com.gpl.rpg.AndorsTrail.model.actor.Monster; import com.gpl.rpg.AndorsTrail.model.actor.Player; +import com.gpl.rpg.AndorsTrail.model.listeners.ActorStatsListener; import com.gpl.rpg.AndorsTrail.util.Coord; -import com.gpl.rpg.AndorsTrail.util.Range; -public final class CombatView extends RelativeLayout { +public final class CombatView extends RelativeLayout implements CombatSelectionListener, CombatTurnListener, ActorStatsListener { private final TextView statusTextView; private final Button attackMoveButton; private final ImageButton monsterInfo; @@ -47,10 +50,10 @@ public final class CombatView extends RelativeLayout { public CombatView(final Context context, AttributeSet attr) { super(context, attr); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivityContext(context); - this.world = app.world; + this.world = app.getWorld(); this.player = world.model.player; - this.view = app.currentView.get(); - this.preferences = app.preferences; + this.view = app.getViewContext(); + this.preferences = app.getPreferences(); this.res = getResources(); setFocusable(false); @@ -87,7 +90,7 @@ public final class CombatView extends RelativeLayout { monsterInfo.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { - Dialogs.showMonsterInfo(view.mainActivity, currentMonster); + Dialogs.showMonsterInfo(context, currentMonster); } }); @@ -111,7 +114,7 @@ public final class CombatView extends RelativeLayout { }); } - public void updateTurnInfo(Monster currentActiveMonster) { + private void updateTurnInfo(Monster currentActiveMonster) { if (currentActiveMonster != null) { actionBar.setVisibility(View.INVISIBLE); monsterActionText.setVisibility(View.VISIBLE); @@ -122,25 +125,30 @@ public final class CombatView extends RelativeLayout { } } - private void updateMonsterHealth(Range range) { - monsterHealth.update(range); + private void updateMonsterHealth(Monster m) { + monsterHealth.update(m.getMaxHP(), m.getCurrentHP()); } - private void updatePlayerAP(Range range) { - statusTextView.setText(res.getString(R.string.combat_status_ap, range.current)); + private void updatePlayerAP() { + statusTextView.setText(res.getString(R.string.combat_status_ap, player.getCurrentAP())); } - public void updateCombatSelection(Monster selectedMonster, Coord selectedMovePosition) { + private void updateSelectedMonster(Monster selectedMonster) { if (currentMonster != null && currentMonster == selectedMonster) return; attackMoveButton.setEnabled(true); monsterBar.setVisibility(View.INVISIBLE); currentMonster = null; if (selectedMonster != null) { - attackMoveButton.setText(res.getString(R.string.combat_attack, player.getAttackCost())); monsterBar.setVisibility(View.VISIBLE); world.tileManager.setImageViewTile(monsterInfo, selectedMonster); - updateMonsterHealth(selectedMonster.health); + updateMonsterHealth(selectedMonster); currentMonster = selectedMonster; - } else if (selectedMovePosition != null) { + } + } + + private void updateAttackMoveButtonText() { + if (world.model.uiSelections.selectedMonster != null) { + attackMoveButton.setText(res.getString(R.string.combat_attack, player.getAttackCost())); + } else if (world.model.uiSelections.selectedPosition != null) { attackMoveButton.setText(res.getString(R.string.combat_move, player.getMoveCost())); } else { attackMoveButton.setText(res.getString(R.string.combat_attack, player.getAttackCost())); @@ -148,14 +156,13 @@ public final class CombatView extends RelativeLayout { } public void updateStatus() { - updatePlayerAP(player.ap); - if (world.model.uiSelections.selectedMonster != null) { - updateMonsterHealth(world.model.uiSelections.selectedMonster.health); - } - updateCombatSelection(world.model.uiSelections.selectedMonster, world.model.uiSelections.selectedPosition); + updatePlayerAP(); + updateSelectedMonster(world.model.uiSelections.selectedMonster); + updateAttackMoveButtonText(); } public void show() { + updateStatus(); setVisibility(View.VISIBLE); bringToFront(); if (preferences.enableUiAnimations) { @@ -170,4 +177,71 @@ public final class CombatView extends RelativeLayout { setVisibility(View.GONE); } } + + public void subscribe() { + view.combatController.combatSelectionListeners.add(this); + view.combatController.combatTurnListeners.add(this); + view.actorStatsController.actorStatsListeners.add(this); + } + public void unsubscribe() { + view.actorStatsController.actorStatsListeners.remove(this); + view.combatController.combatTurnListeners.remove(this); + view.combatController.combatSelectionListeners.remove(this); + } + + @Override + public void onMonsterSelected(Monster m, Coord selectedPosition, Coord previousSelection) { + updateSelectedMonster(m); + } + + @Override + public void onMovementDestinationSelected(Coord selectedPosition, Coord previousSelection) { + updateSelectedMonster(null); + } + + @Override + public void onCombatSelectionCleared(Coord previousSelection) { + updateSelectedMonster(null); + } + + @Override + public void onCombatStarted() { + show(); + updateTurnInfo(null); + } + + @Override + public void onCombatEnded() { + hide(); + } + + @Override + public void onNewPlayerTurn() { + updateTurnInfo(null); + } + + @Override + public void onMonsterIsAttacking(Monster m) { + updateTurnInfo(m); + } + + @Override + public void onActorHealthChanged(Actor actor) { + if (actor == currentMonster) updateMonsterHealth(currentMonster); + } + + @Override + public void onActorAPChanged(Actor actor) { + if (actor == player) updatePlayerAP(); + } + + @Override + public void onActorAttackCostChanged(Actor actor, int newAttackCost) { + if (actor == player) updateAttackMoveButtonText(); + } + + @Override + public void onActorMoveCostChanged(Actor actor, int newMoveCost) { + if (actor == player) updateAttackMoveButtonText(); + } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/DisplayActiveActorConditionIcons.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/DisplayActiveActorConditionIcons.java index c14864707..fe0c3db62 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/DisplayActiveActorConditionIcons.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/DisplayActiveActorConditionIcons.java @@ -16,33 +16,39 @@ import android.widget.RelativeLayout.LayoutParams; import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences; 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.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 { +public final class DisplayActiveActorConditionIcons implements ActorConditionListener { private final AndorsTrailPreferences preferences; private final TileManager tileManager; + private final ViewContext view; + private final WorldContext world; private final RelativeLayout activeConditions; private final ArrayList currentConditionIcons = new ArrayList(); private final WeakReference androidContext; public DisplayActiveActorConditionIcons( - final AndorsTrailPreferences preferences, - final TileManager tileManager, + final ViewContext view, + final WorldContext world, Context androidContext, RelativeLayout activeConditions) { - this.preferences = preferences; - this.tileManager = tileManager; + this.view = view; + this.world = world; + this.preferences = view.preferences; + this.tileManager = world.tileManager; this.androidContext = new WeakReference(androidContext); this.activeConditions = activeConditions; } @Override public void onActorConditionAdded(Actor actor, ActorCondition condition) { + if (actor != world.model.player) return; ActiveConditionIcon icon = getFirstFreeIcon(); icon.setActiveCondition(condition); icon.show(); @@ -50,6 +56,7 @@ public class DisplayActiveActorConditionIcons implements ActorConditionListener @Override public void onActorConditionRemoved(Actor actor, ActorCondition condition) { + if (actor != world.model.player) return; ActiveConditionIcon icon = getIconFor(condition); if (icon == null) return; icon.hide(true); @@ -61,6 +68,7 @@ public class DisplayActiveActorConditionIcons implements ActorConditionListener @Override public void onActorConditionMagnitudeChanged(Actor actor, ActorCondition condition) { + if (actor != world.model.player) return; ActiveConditionIcon icon = getIconFor(condition); if (icon == null) return; icon.setIconText(); @@ -68,22 +76,23 @@ public class DisplayActiveActorConditionIcons implements ActorConditionListener @Override public void onActorConditionRoundEffectApplied(Actor actor, ActorCondition condition) { + if (actor != world.model.player) return; ActiveConditionIcon icon = getIconFor(condition); if (icon == null) return; icon.pulseAnimate(); } - public void unsubscribe(final WorldContext world) { - world.model.player.conditionListener.remove(this); + public void unsubscribe() { + view.actorStatsController.actorConditionListeners.remove(this); for (ActiveConditionIcon icon : currentConditionIcons) icon.condition = null; } - public void subscribe(final WorldContext world) { + public void subscribe() { for (ActiveConditionIcon icon : currentConditionIcons) icon.hide(false); for (ActorCondition condition : world.model.player.conditions) { getFirstFreeIcon().setActiveCondition(condition); } - world.model.player.conditionListener.add(this); + view.actorStatsController.actorConditionListeners.add(this); } private final class ActiveConditionIcon implements AnimationListener { @@ -168,7 +177,7 @@ public class DisplayActiveActorConditionIcons implements ActorConditionListener @Override public void onAnimationStart(Animation animation) { } } - protected void rearrangeIconsLeftOf(ActiveConditionIcon icon) { + private void rearrangeIconsLeftOf(ActiveConditionIcon icon) { int i = currentConditionIcons.indexOf(icon); currentConditionIcons.remove(i); currentConditionIcons.add(icon); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java index 177ba4c89..501a88419 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java @@ -7,6 +7,7 @@ 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.VisualEffectAnimation; +import com.gpl.rpg.AndorsTrail.controller.listeners.*; import com.gpl.rpg.AndorsTrail.model.ModelContainer; import com.gpl.rpg.AndorsTrail.model.actor.Monster; import com.gpl.rpg.AndorsTrail.model.item.Loot; @@ -31,7 +32,15 @@ import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; -public final class MainView extends SurfaceView implements SurfaceHolder.Callback { +public final class MainView extends SurfaceView + implements SurfaceHolder.Callback, + PlayerMovementListener, + CombatSelectionListener, + MonsterSpawnListener, + MonsterMovementListener, + LootBagListener, + VisualEffectFrameListener, + GameRoundListener { private final int tileSize; private float scale; @@ -58,18 +67,19 @@ public final class MainView extends SurfaceView implements SurfaceHolder.Callbac private TileCollection tiles; private final Coord playerPosition = new Coord(); private Size surfaceSize; + private boolean redrawNextTick = false; public MainView(Context context, AttributeSet attr) { super(context, attr); this.holder = getHolder(); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivityContext(context); - this.view = app.currentView.get(); - this.model = app.world.model; - this.world = app.world; + this.view = app.getViewContext(); + this.world = app.getWorld(); + this.model = world.model; this.tileSize = world.tileManager.tileSize; this.inputController = view.inputController; - this.preferences = app.preferences; + this.preferences = app.getPreferences(); holder.addCallback(this); @@ -97,7 +107,7 @@ public final class MainView extends SurfaceView implements SurfaceHolder.Callbac } @Override - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + public void surfaceChanged(SurfaceHolder sh, int format, int w, int h) { if (w <= 0 || h <= 0) return; this.scale = world.tileManager.scale; @@ -110,19 +120,19 @@ public final class MainView extends SurfaceView implements SurfaceHolder.Callbac ); if (model.currentMap != null) { - notifyMapChanged(model); + onPlayerEnteredNewMap(model.currentMap, model.player.position); + } else { + redrawAll(REDRAW_ALL_SURFACE_CHANGED); } - - redrawAll(REDRAW_ALL_SURFACE_CHANGED); } @Override - public void surfaceCreated(SurfaceHolder holder) { + public void surfaceCreated(SurfaceHolder sh) { hasSurface = true; } @Override - public void surfaceDestroyed(SurfaceHolder holder) { + public void surfaceDestroyed(SurfaceHolder sh) { hasSurface = false; } @@ -152,25 +162,26 @@ public final class MainView extends SurfaceView implements SurfaceHolder.Callbac return true; } - public static final int REDRAW_ALL_SURFACE_CHANGED = 1; - public static final int REDRAW_ALL_MAP_CHANGED = 2; - public static final int REDRAW_ALL_PLAYER_MOVED = 3; - public static final int REDRAW_ALL_MONSTER_MOVED = 4; - public static final int REDRAW_ALL_MONSTER_KILLED = 10; - public static final int REDRAW_AREA_EFFECT_STARTING = 5; - public static final int REDRAW_AREA_EFFECT_COMPLETED = 6; - public static final int REDRAW_TILE_SELECTION_REMOVED = 7; - public static final int REDRAW_TILE_SELECTION_ADDED = 8; - public static final int REDRAW_TILE_BAG = 9; - - public void redrawAll(int why) { + private static final int REDRAW_ALL_SURFACE_CHANGED = 1; + private static final int REDRAW_ALL_MAP_CHANGED = 2; + private static final int REDRAW_ALL_PLAYER_MOVED = 3; + private static final int REDRAW_AREA_MONSTER_MOVED = 4; + private static final int REDRAW_AREA_MONSTER_KILLED = 10; + private static final int REDRAW_AREA_EFFECT_COMPLETED = 6; + private static final int REDRAW_AREA_MONSTER_SPAWNED = 11; + private static final int REDRAW_TILE_SELECTION_REMOVED = 7; + private static final int REDRAW_TILE_SELECTION_ADDED = 8; + private static final int REDRAW_TILE_BAG = 9; + private static final int REDRAW_TILE_SPLATTER = 12; + + private void redrawAll(int why) { redrawArea_(mapViewArea); } - public void redrawTile(final Coord p, int why) { + private void redrawTile(final Coord p, int why) { p1x1.topLeft.set(p); redrawArea_(p1x1); } - public void redrawArea(final CoordRect area, int why) { + private void redrawArea(final CoordRect area, int why) { redrawArea_(area); } private void redrawArea_(CoordRect area) { @@ -205,7 +216,7 @@ public final class MainView extends SurfaceView implements SurfaceHolder.Callbac return true; } private final Rect redrawRect = new Rect(); - public void redrawAreaWithEffect(final VisualEffectAnimation effect, int tileID, int textYOffset, Paint textPaint) { + private void redrawAreaWithEffect(final VisualEffectAnimation effect, int tileID, int textYOffset) { CoordRect area = effect.area; if (!hasSurface) return; if (shouldRedrawEverythingForVisualEffect()) area = mapViewArea; @@ -222,7 +233,7 @@ public final class MainView extends SurfaceView implements SurfaceHolder.Callbac doDrawRect(c, area); drawFromMapPosition(c, area, effect.position, tileID); if (effect.displayText != null) { - drawEffectText(c, area, effect, textYOffset, textPaint); + drawEffectText(c, area, effect, textYOffset, effect.textPaint); } } } } finally { @@ -266,7 +277,7 @@ public final class MainView extends SurfaceView implements SurfaceHolder.Callbac private void doDrawRect(Canvas canvas, CoordRect area) { drawMapLayer(canvas, area, currentTileMap.layers[LayeredTileMap.LAYER_GROUND]); - tryDrawMapLayer(canvas, area, currentTileMap, LayeredTileMap.LAYER_OBJECTS); + tryDrawMapLayer(canvas, area, LayeredTileMap.LAYER_OBJECTS); for (BloodSplatter splatter : currentMap.splatters) { drawFromMapPosition(canvas, area, splatter.position, splatter.iconID); @@ -285,7 +296,7 @@ public final class MainView extends SurfaceView implements SurfaceHolder.Callbac } } - tryDrawMapLayer(canvas, area, currentTileMap, LayeredTileMap.LAYER_ABOVE); + tryDrawMapLayer(canvas, area, LayeredTileMap.LAYER_ABOVE); if (model.uiSelections.selectedPosition != null) { if (model.uiSelections.selectedMonster != null) { @@ -296,7 +307,7 @@ public final class MainView extends SurfaceView implements SurfaceHolder.Callbac } } - private void tryDrawMapLayer(Canvas canvas, final CoordRect area, final LayeredTileMap currentTileMap, final int layerIndex) { + private void tryDrawMapLayer(Canvas canvas, final CoordRect area, final int layerIndex) { if (currentTileMap.layers.length > layerIndex) drawMapLayer(canvas, area, currentTileMap.layers[layerIndex]); } @@ -338,9 +349,10 @@ public final class MainView extends SurfaceView implements SurfaceHolder.Callbac canvas.drawText(e.displayText, x, y, textPaint); } - public void notifyMapChanged(ModelContainer model) { + @Override + public void onPlayerEnteredNewMap(PredefinedMap map, Coord p) { synchronized (holder) { - currentMap = model.currentMap; + currentMap = map; currentTileMap = model.currentTileMap; tiles = world.tileManager.currentMapTiles; @@ -379,9 +391,131 @@ public final class MainView extends SurfaceView implements SurfaceHolder.Callbac } } } - - public void notifyPlayerMoved(Coord newPosition) { + + @Override + public void onPlayerMoved(Coord newPosition, Coord previousPosition) { recalculateMapTopLeft(newPosition); redrawAll(REDRAW_ALL_PLAYER_MOVED); } + + public void subscribe() { + view.gameRoundController.gameRoundListeners.add(this); + view.effectController.visualEffectFrameListeners.add(this); + view.itemController.lootBagListeners.add(this); + view.movementController.playerMovementListeners.add(this); + view.combatController.combatSelectionListeners.add(this); + view.monsterSpawnController.monsterSpawnListeners.add(this); + view.monsterMovementController.monsterMovementListeners.add(this); + } + public void unsubscribe() { + view.monsterMovementController.monsterMovementListeners.remove(this); + view.monsterSpawnController.monsterSpawnListeners.remove(this); + view.combatController.combatSelectionListeners.remove(this); + view.movementController.playerMovementListeners.remove(this); + view.itemController.lootBagListeners.remove(this); + view.effectController.visualEffectFrameListeners.remove(this); + view.gameRoundController.gameRoundListeners.remove(this); + } + + @Override + public void onMonsterSelected(Monster m, Coord selectedPosition, Coord previousSelection) { + if (previousSelection != null) redrawTile(previousSelection, REDRAW_TILE_SELECTION_REMOVED); + redrawTile(selectedPosition, REDRAW_TILE_SELECTION_ADDED); + } + + @Override + public void onMovementDestinationSelected(Coord selectedPosition, Coord previousSelection) { + if (previousSelection != null) redrawTile(previousSelection, REDRAW_TILE_SELECTION_REMOVED); + redrawTile(selectedPosition, REDRAW_TILE_SELECTION_ADDED); + } + + @Override + public void onCombatSelectionCleared(Coord previousSelection) { + redrawTile(previousSelection, REDRAW_TILE_SELECTION_REMOVED); + } + + @Override + public void onMonsterSpawned(PredefinedMap map, Monster m) { + if (map != currentMap) return; + if (!mapViewArea.intersects(m.rectPosition)) return; + redrawNextTick = true; + } + + @Override + public void onMonsterRemoved(PredefinedMap map, Monster m, CoordRect previousPosition) { + if (map != currentMap) return; + if (!mapViewArea.intersects(m.rectPosition)) return; + redrawArea(previousPosition, REDRAW_AREA_MONSTER_KILLED); + } + + @Override + public void onMonsterSteppedOnPlayer(Monster m) { + } + + @Override + public void onMonsterMoved(PredefinedMap map, Monster m, CoordRect previousPosition) { + if (map != currentMap) return; + if (!mapViewArea.intersects(m.rectPosition)) return; + redrawNextTick = true; + } + + @Override + public void onSplatterAdded(PredefinedMap map, Coord p) { + if (map != currentMap) return; + if (!mapViewArea.contains(p)) return; + redrawNextTick = true; + } + + @Override + public void onSplatterChanged(PredefinedMap map, Coord p) { + if (map != currentMap) return; + if (!mapViewArea.contains(p)) return; + redrawNextTick = true; + } + + @Override + public void onSplatterRemoved(PredefinedMap map, Coord p) { + if (map != currentMap) return; + if (!mapViewArea.contains(p)) return; + redrawNextTick = true; + } + + @Override + public void onLootBagCreated(PredefinedMap map, Coord p) { + if (map != currentMap) return; + if (!mapViewArea.contains(p)) return; + redrawTile(p, REDRAW_TILE_BAG); + } + + @Override + public void onLootBagRemoved(PredefinedMap map, Coord p) { + if (map != currentMap) return; + if (!mapViewArea.contains(p)) return; + redrawTile(p, REDRAW_TILE_BAG); + } + + @Override + public void onNewAnimationFrame(VisualEffectAnimation animation, int tileID, int textYOffset) { + redrawAreaWithEffect(animation, tileID, textYOffset); + } + + @Override + public void onAnimationCompleted(VisualEffectAnimation animation) { + redrawArea(animation.area, REDRAW_AREA_EFFECT_COMPLETED); + } + + @Override + public void onNewTick() { + if (!redrawNextTick) return; + + redrawAll(REDRAW_ALL_PLAYER_MOVED); + + redrawNextTick = false; + } + + @Override + public void onNewRound() { } + + @Override + public void onNewFullRound() { } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/QuickButton.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/QuickButton.java index f590bda7b..3606f7981 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/QuickButton.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/QuickButton.java @@ -13,7 +13,7 @@ import android.util.AttributeSet; import android.view.ContextMenu; import android.widget.Button; -public class QuickButton extends Button { +public final class QuickButton extends Button { private final ColorFilter grayScaleFilter = new ColorMatrixColorFilter( new float[] { 0.30f, 0.59f, 0.11f, 0.0f, 0.0f, 0.30f, 0.59f, 0.11f, 0.0f, 0.0f, @@ -21,7 +21,7 @@ public class QuickButton extends Button { 0.00f, 0.00f, 0.00f, 1.0f, 0.0f }); private boolean empty; - private QuickButtonContextMenuInfo menuInfo; + private final QuickButtonContextMenuInfo menuInfo; private final int textPadding; public QuickButton(Context context, AttributeSet attrs) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/QuickitemView.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/QuickitemView.java index 049673024..17b1ced63 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/QuickitemView.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/QuickitemView.java @@ -16,11 +16,12 @@ import com.gpl.rpg.AndorsTrail.R; import com.gpl.rpg.AndorsTrail.activity.MainActivity; import com.gpl.rpg.AndorsTrail.context.ViewContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; +import com.gpl.rpg.AndorsTrail.controller.listeners.QuickSlotListener; import com.gpl.rpg.AndorsTrail.model.item.Inventory; import com.gpl.rpg.AndorsTrail.model.item.ItemType; import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection; -public class QuickitemView extends LinearLayout implements OnClickListener { +public final class QuickitemView extends LinearLayout implements OnClickListener, QuickSlotListener { private static final int NUM_QUICK_SLOTS = Inventory.NUM_QUICK_SLOTS; private final WorldContext world; @@ -32,8 +33,8 @@ public class QuickitemView extends LinearLayout implements OnClickListener { public QuickitemView(Context context, AttributeSet attrs) { super(context, attrs); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivityContext(context); - this.world = app.world; - this.view = app.currentView.get(); + this.world = app.getWorld(); + this.view = app.getViewContext(); setFocusable(false); setOrientation(LinearLayout.HORIZONTAL); @@ -110,4 +111,21 @@ public class QuickitemView extends LinearLayout implements OnClickListener { for(QuickButton item: buttons) mainActivity.registerForContextMenu(item); } + + @Override + public void onQuickSlotChanged(int slotId) { + refreshQuickitems(); + } + + @Override + public void onQuickSlotUsed(int slotId) { + refreshQuickitems(); + } + + public void subscribe() { + view.itemController.quickSlotListeners.add(this); + } + public void unsubscribe() { + view.itemController.quickSlotListeners.remove(this); + } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/RangeBar.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/RangeBar.java index 13fdf89c7..ed67c73a3 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/RangeBar.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/RangeBar.java @@ -32,12 +32,13 @@ public final class RangeBar extends RelativeLayout { labelText.setText(labelTextID); } - public void update(final Range range) { + public void update(final Range range) { update(range.max, range.current); } + public void update(final int max, final int current) { progressBar.setProgress(0); // http://stackoverflow.com/questions/4348032/android-progressbar-does-not-update-progress-view-drawable - progressBar.setMax(range.max); - progressBar.setProgress(Math.min(range.current, range.max)); - progressBarText.setText(range.toString()); + progressBar.setMax(max); + progressBar.setProgress(Math.min(current, max)); + progressBarText.setText(current + "/" + max); invalidate(); } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/SkillListAdapter.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/SkillListAdapter.java index 02d7c9f1f..8b448c7ad 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/SkillListAdapter.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/SkillListAdapter.java @@ -41,7 +41,7 @@ public final class SkillListAdapter extends ArrayAdapter { public int compare(SkillInfo a, SkillInfo b) { return a.id - b.id; } - }); + }); return result; } @@ -68,7 +68,7 @@ public final class SkillListAdapter extends ArrayAdapter { String skillTitle = r.getString(SkillInfoActivity.getSkillTitleResourceID(skillID)); final int skillLevel = player.getSkillLevel(skillID); if (skillLevel > 0) { - skillTitle += " (" + skillLevel + ")"; + skillTitle += " (" + skillLevel + ')'; } title.setText(skillTitle); description.setText(getSkillShortDescriptionResourceID(skillID)); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/StatusView.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/StatusView.java index c6edb3ce6..3a95a8c52 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/StatusView.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/StatusView.java @@ -3,8 +3,12 @@ package com.gpl.rpg.AndorsTrail.view; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.R; 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.listeners.PlayerStatsListener; +import com.gpl.rpg.AndorsTrail.model.actor.Actor; import com.gpl.rpg.AndorsTrail.model.actor.Player; +import com.gpl.rpg.AndorsTrail.model.listeners.ActorStatsListener; import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager; import android.content.Context; @@ -17,8 +21,9 @@ import android.view.View; import android.widget.RelativeLayout; import android.widget.ImageButton; -public final class StatusView extends RelativeLayout { +public final class StatusView extends RelativeLayout implements PlayerStatsListener, ActorStatsListener { + private final ViewContext view; private final WorldContext world; private final Player player; @@ -33,8 +38,9 @@ public final class StatusView extends RelativeLayout { public StatusView(final Context context, AttributeSet attr) { super(context, attr); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivityContext(context); - this.world = app.world; - this.player = app.world.model.player; + this.view = app.getViewContext(); + this.world = app.getWorld(); + this.player = world.model.player; setFocusable(false); inflate(context, R.layout.statusview, this); @@ -80,8 +86,24 @@ public final class StatusView extends RelativeLayout { } public void updateStatus() { - healthBar.update(player.health); - expBar.update(player.levelExperience); + updateHealth(); + updateExperience(); + } + + public void subscribe() { + view.actorStatsController.actorStatsListeners.add(this); + view.actorStatsController.playerStatsListeners.add(this); + } + public void unsubscribe() { + view.actorStatsController.playerStatsListeners.remove(this); + view.actorStatsController.actorStatsListeners.remove(this); + } + + private void updateHealth() { + healthBar.update(player.getMaxHP(), player.getCurrentHP()); + } + private void updateExperience() { + expBar.update(player.getMaxLevelExperience(), player.getCurrentLevelExperience()); boolean canLevelUp = player.canLevelup(); if (showingLevelup != canLevelUp) { updateIcon(canLevelUp); @@ -96,4 +118,23 @@ public final class StatusView extends RelativeLayout { world.tileManager.setImageViewTile(heroImage, player); } } + + @Override + public void onActorHealthChanged(Actor actor) { + if (actor == player) updateHealth(); + } + + @Override + public void onActorAPChanged(Actor actor) { } + + @Override + public void onActorAttackCostChanged(Actor actor, int newAttackCost) { } + + @Override + public void onActorMoveCostChanged(Actor actor, int newMoveCost) { } + + @Override + public void onPlayerExperienceChanged(Player p) { + updateExperience(); + } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/ToolboxView.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/ToolboxView.java index c4caa9e4b..3fee20a5b 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/ToolboxView.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/ToolboxView.java @@ -17,7 +17,7 @@ import com.gpl.rpg.AndorsTrail.context.WorldContext; import com.gpl.rpg.AndorsTrail.controller.WorldMapController; import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager; -public class ToolboxView extends LinearLayout implements OnClickListener { +public final class ToolboxView extends LinearLayout implements OnClickListener { private final WorldContext world; private final AndorsTrailPreferences preferences; private final Animation showAnimation; @@ -30,8 +30,8 @@ public class ToolboxView extends LinearLayout implements OnClickListener { public ToolboxView(final Context context, AttributeSet attrs) { super(context, attrs); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivityContext(context); - this.world = app.world; - this.preferences = app.preferences; + this.world = app.getWorld(); + this.preferences = app.getPreferences(); inflate(context, R.layout.toolboxview, this); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/TraitsInfoView.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/TraitsInfoView.java index 8a13a6ddd..ded568798 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/TraitsInfoView.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/TraitsInfoView.java @@ -61,12 +61,12 @@ public final class TraitsInfoView { tv.setText(Integer.toString(attackCost)); row = (TableRow) group.findViewById(R.id.traitsinfo_attack_chance_row); - if (attackChance != 0) { + if (attackChance == 0) { + row.setVisibility(View.GONE); + } else { row.setVisibility(View.VISIBLE); tv = (TextView) group.findViewById(R.id.traitsinfo_attack_chance); - tv.setText(Integer.toString(attackChance) + "%"); - } else { - row.setVisibility(View.GONE); + tv.setText(Integer.toString(attackChance) + '%'); } row = (TableRow) group.findViewById(R.id.traitsinfo_attack_damage_row); @@ -79,12 +79,12 @@ public final class TraitsInfoView { } row = (TableRow) group.findViewById(R.id.traitsinfo_criticalhit_skill_row); - if (criticalSkill != 0) { + if (criticalSkill == 0) { + row.setVisibility(View.GONE); + } else { row.setVisibility(View.VISIBLE); tv = (TextView) group.findViewById(R.id.traitsinfo_criticalhit_skill); tv.setText(Integer.toString(criticalSkill)); - } else { - row.setVisibility(View.GONE); } row = (TableRow) group.findViewById(R.id.traitsinfo_criticalhit_multiplier_row); @@ -100,27 +100,27 @@ public final class TraitsInfoView { 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)) + "%"); + tv.setText(Integer.toString(Actor.getEffectiveCriticalChance(criticalSkill)) + '%'); } else { row.setVisibility(View.GONE); } row = (TableRow) group.findViewById(R.id.traitsinfo_block_chance_row); - if (blockChance != 0) { + if (blockChance == 0) { + row.setVisibility(View.GONE); + } else { row.setVisibility(View.VISIBLE); tv = (TextView) group.findViewById(R.id.traitsinfo_block_chance); - tv.setText(Integer.toString(blockChance) + "%"); - } else { - row.setVisibility(View.GONE); + tv.setText(Integer.toString(blockChance) + '%'); } row = (TableRow) group.findViewById(R.id.traitsinfo_damageresist_row); - if (damageResistance != 0) { + if (damageResistance == 0) { + row.setVisibility(View.GONE); + } else { row.setVisibility(View.VISIBLE); tv = (TextView) group.findViewById(R.id.traitsinfo_damageresist); tv.setText(Integer.toString(damageResistance)); - } else { - row.setVisibility(View.GONE); } row = (TableRow) group.findViewById(R.id.traitsinfo_is_immune_to_critical_hits_row); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/VirtualDpadView.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/VirtualDpadView.java index 6f6b84d5a..621f495b3 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/VirtualDpadView.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/VirtualDpadView.java @@ -18,7 +18,6 @@ import com.gpl.rpg.AndorsTrail.controller.InputController; public final class VirtualDpadView extends ImageView implements OnClickListener { private final WorldContext world; - private final ViewContext view; private final InputController inputController; private int one_third_width; @@ -35,9 +34,9 @@ public final class VirtualDpadView extends ImageView implements OnClickListener public VirtualDpadView(final Context context, AttributeSet attr) { super(context, attr); AndorsTrailApplication app = AndorsTrailApplication.getApplicationFromActivityContext(context); - this.world = app.world; - this.view = app.currentView.get(); - this.inputController = this.view.inputController; + this.world = app.getWorld(); + final ViewContext view = app.getViewContext(); + this.inputController = view.inputController; setImageResource(R.drawable.ui_dpad); setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); @@ -106,30 +105,39 @@ public final class VirtualDpadView extends ImageView implements OnClickListener isMinimizeable = preferences.dpadMinimizeable; RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); - if (dpadPosition == AndorsTrailPreferences.DPAD_POSITION_LOWER_RIGHT) { - params.addRule(RelativeLayout.ALIGN_RIGHT, R.id.main_mainview); - params.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.main_mainview); - } else if (dpadPosition == AndorsTrailPreferences.DPAD_POSITION_LOWER_LEFT) { - params.addRule(RelativeLayout.ALIGN_LEFT, R.id.main_mainview); - params.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.main_mainview); - } else if (dpadPosition == AndorsTrailPreferences.DPAD_POSITION_LOWER_CENTER) { - params.addRule(RelativeLayout.CENTER_HORIZONTAL); - params.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.main_mainview); - } else if (dpadPosition == AndorsTrailPreferences.DPAD_POSITION_UPPER_RIGHT) { - params.addRule(RelativeLayout.ALIGN_RIGHT, R.id.main_mainview); - params.addRule(RelativeLayout.ALIGN_TOP, R.id.main_mainview); - } else if (dpadPosition == AndorsTrailPreferences.DPAD_POSITION_UPPER_LEFT) { - params.addRule(RelativeLayout.ALIGN_LEFT, R.id.main_mainview); - params.addRule(RelativeLayout.ALIGN_TOP, R.id.main_mainview); - } else if (dpadPosition == AndorsTrailPreferences.DPAD_POSITION_UPPER_CENTER) { - params.addRule(RelativeLayout.CENTER_HORIZONTAL); - params.addRule(RelativeLayout.ALIGN_TOP, R.id.main_mainview); - } else if (dpadPosition == AndorsTrailPreferences.DPAD_POSITION_CENTER_LEFT) { - params.addRule(RelativeLayout.ALIGN_LEFT, R.id.main_mainview); - params.addRule(RelativeLayout.CENTER_VERTICAL); - } else if (dpadPosition == AndorsTrailPreferences.DPAD_POSITION_CENTER_RIGHT) { - params.addRule(RelativeLayout.ALIGN_RIGHT, R.id.main_mainview); - params.addRule(RelativeLayout.CENTER_VERTICAL); + switch (dpadPosition) { + case AndorsTrailPreferences.DPAD_POSITION_LOWER_RIGHT: + params.addRule(RelativeLayout.ALIGN_RIGHT, R.id.main_mainview); + params.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.main_mainview); + break; + case AndorsTrailPreferences.DPAD_POSITION_LOWER_LEFT: + params.addRule(RelativeLayout.ALIGN_LEFT, R.id.main_mainview); + params.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.main_mainview); + break; + case AndorsTrailPreferences.DPAD_POSITION_LOWER_CENTER: + params.addRule(RelativeLayout.CENTER_HORIZONTAL); + params.addRule(RelativeLayout.ALIGN_BOTTOM, R.id.main_mainview); + break; + case AndorsTrailPreferences.DPAD_POSITION_UPPER_RIGHT: + params.addRule(RelativeLayout.ALIGN_RIGHT, R.id.main_mainview); + params.addRule(RelativeLayout.ALIGN_TOP, R.id.main_mainview); + break; + case AndorsTrailPreferences.DPAD_POSITION_UPPER_LEFT: + params.addRule(RelativeLayout.ALIGN_LEFT, R.id.main_mainview); + params.addRule(RelativeLayout.ALIGN_TOP, R.id.main_mainview); + break; + case AndorsTrailPreferences.DPAD_POSITION_UPPER_CENTER: + params.addRule(RelativeLayout.CENTER_HORIZONTAL); + params.addRule(RelativeLayout.ALIGN_TOP, R.id.main_mainview); + break; + case AndorsTrailPreferences.DPAD_POSITION_CENTER_LEFT: + params.addRule(RelativeLayout.ALIGN_LEFT, R.id.main_mainview); + params.addRule(RelativeLayout.CENTER_VERTICAL); + break; + case AndorsTrailPreferences.DPAD_POSITION_CENTER_RIGHT: + params.addRule(RelativeLayout.ALIGN_RIGHT, R.id.main_mainview); + params.addRule(RelativeLayout.CENTER_VERTICAL); + break; } setLayoutParams(params);