diff --git a/AndorsTrail/AndroidManifest.xml b/AndorsTrail/AndroidManifest.xml index 0bc0e769a..d7cee9028 100644 --- a/AndorsTrail/AndroidManifest.xml +++ b/AndorsTrail/AndroidManifest.xml @@ -3,8 +3,8 @@ - - - + + + @string/preferences_language_default English - Deutsch (96%) - Español (90%) - Française (57%) + Deutsch (99%) + Español (91%) + Française (58%) Italiano (90%) Magyar (44%) - Polski (94%) + Polski (100%) Português (78%) Português Brasil (82%) Русский язык (100%) diff --git a/AndorsTrail/res/values/strings.xml b/AndorsTrail/res/values/strings.xml index bf9fb028c..f2dc185f6 100644 --- a/AndorsTrail/res/values/strings.xml +++ b/AndorsTrail/res/values/strings.xml @@ -283,18 +283,16 @@ ]]> Welcome - - Thank you for downloading Andor\'s Trail!\n\n - Please note that this version of Andor\'s Trail is a WORK IN PROGRESS, which means that all maps are not yet complete.\n - Please visit the project forums to discuss the game with other players or to help make the game even better (see "about").\n - \n - Thanks for all the feedback! + Thank you for downloading Andor\'s Trail!\n\nPlease note that this version of Andor\'s Trail is a WORK IN PROGRESS, which means that all maps are not yet complete.\nPlease visit the project forums to discuss the game with other players or to help make the game even better (see "about").\n\nThanks for all the feedback! + \n\nIn order to save and load your games (and only for this purpose) Andor\'s Trail will ask you for permission to access your storage. + Loading and saving games + Andor\'s Trail writes saved games to user accessible storage on your device. This allows you to easily back up your saved games or transfer them to a new device. Please visit our forums for more information.\n\nAndor\'s Trail does not use access to your device for any other purpose and does not access the internet. Andor\'s Trail is open source; the sources can be found on github. Select quests to show - Hide completed quests - Include completed quests - Only completed quests + Active quests + All quests + Completed quests Status: %1$s In progress Completed @@ -373,7 +371,7 @@ System language Language - Select the language. English is used if the system language is not available or content has not ben translated. (Requires restart) + Select the language. English is used if the system language is not available or content has not been translated. (Requires restart) Assign quick slot Select item to assign @@ -563,6 +561,7 @@ Attack damage: %1$d Attack damage: %1$d-%2$d Increases attack damage by %1$d + Damage modifier: %1$d%% Increases attack damage by %1$d-%2$d Lowers attack damage by %1$d Lowers attack damage by %1$d-%2$d @@ -613,6 +612,7 @@ Fighting style: Dual wield Fighting style: Two-handed weapon Fighting style: Weapon and shield + Fighting style: Way of the monk Specialization: Dual wield Specialization: Two-handed weapon Specialization: Weapon and shield @@ -624,13 +624,14 @@ Better at fighting with axes Better at fighting with bludgeoning weapons Better at fighting without weapons - Make better use of shields + Make better use of shields and parrying weapons Better at fighting without armor Make better use of light armor Make better use of heavy armor Wield two weapons at the same time Make better use of weapons that require both hands Better at fighting with weapon and shield + Better at fighting unarmed/unarmored Expert at dual wielding Expert at two-handed weapons Expert at fighting with weapon and shield @@ -642,7 +643,7 @@ For each skill level, increases attack chance of axes and greataxes by %1$d %% of the item\'s base attack chance, increases block chance by %2$d %% of the item\'s base block chance, and increases critical skill by %3$d %% of the item\'s base critical skill. For each skill level, increases attack chance of bludgeoning weapons by %1$d %% of the item\'s base attack chance, increases block chance by %2$d %% of the item\'s base block chance, and increases critical skill by %3$d %% of the item\'s base critical skill. This includes clubs, quarterstaves, maces, scepters, war hammers and giant hammers. When fighting without a weapon and shield, gain %1$d attack chance, %2$d damage potential and %3$d block chance per skill level. - Increase damage resistance by %1$d per skill level while having a shield equipped. + Increase damage resistance by %1$d per skill level while having a shield or parrying weapon equipped. While fighting without having any piece of armor equipped, gain %1$d block chance per skill level. Items made of cloth are not considered as being armor. For every skill level, increases the block chance of every piece of light armor being worn by %1$d %% of their original block chances. Light armors include leather, light metal and hide armors. For every skill level, increases the block chance of every piece of heavy armor being worn by %1$d %% of their original block chances. Pieces of heavy armor have their movement penalties reduced by %2$d %% per skill level, and their attack speed penalties reduced by %3$d %% per skill level. Heavy armors include metal armors, chain mail and plate mail. @@ -656,12 +657,15 @@ With two levels of this skill, %4$d %% of the off-hand\'s weapon\'s qualities ma "Gives benefits when using weapons that require both hands to wield, such as two-handed swords, greataxes or giant hammers. Every skill level increases damage potential of two-handed weapons with %1$d %% of the original damage potential." - "Gives benefits when fighting with a weapon in the main hand and having a shield equipped in the off-hand. + "Gives benefits when fighting with a weapon in the main hand and having a shield or parrying weapon equipped in the off-hand. -Every skill level increases the attack chance of weapons with %1$d %% of their original attack chances, and the block chance of shields by %2$d %% of their original block chances." +Every skill level increases the attack chance of weapons in the main hand with %1$d %% of their original attack chances, and the block chance of shields or parrying weapons by %2$d %% of their original block chances." + "While fighting without having any piece of armor equipped and without using a weapon or shield, gain %1$d attack chance, %2$d block chance, %3$d damage resistance and increase the maximum damage by %4$d per skill level. The skill also gives a critical multiplier of 1 plus 0.%5$d per level. + +Items made of cloth are not considered as being armor." Increases the attack chance of both wielded weapons by an additional %1$d %% of their original attack chances, in addition to the benefits given by the weapon style skill. The block chances of both wielded weapons are also increased by %2$d %% of their original block chances. Increases damage potential of two-handed weapons by an additional %1$d %% of the original damage potential, in addition to the benefits given by the weapon style skill. The attack chances of two-handed weapons are also increased by %2$d %% of their original attack chances. - Increases both attack chances and damage potential of weapons. The attack chance is increased by %1$d %% of the original attack chance, and the damage potential is increased by %2$d %% of the original damage potential. + Increases both attack chances and damage potential of weapons in the main hand. The attack chance is increased by %1$d %% of the original attack chance, and the damage potential is increased by %2$d %% of the original damage potential. For each skill level, increases attack chance when using pole weapons by %1$d %% of the item\'s base attack chance, increases block chance by %2$d %% of the item\'s base block chance, and increases critical skill by %3$d %% of the item\'s base critical skill. Quickslot position diff --git a/AndorsTrail/res/xml/road1.tmx b/AndorsTrail/res/xml/road1.tmx index 213ecdfbc..a678d66ab 100644 --- a/AndorsTrail/res/xml/road1.tmx +++ b/AndorsTrail/res/xml/road1.tmx @@ -1,5 +1,5 @@ - + @@ -188,22 +188,22 @@ eJy7J8nA8A6IN3Ki4s1QjCwGUncPSe09SYQYMo0sj6yPWHvAWJhEjMV9hOw4KEwaRg4HDPfisMdEmoHBFIjNpAn7AaQWPWyJscMZqM8FiF2lCfvBWRoz7oj1C7qfsGEzJD/gi3dCdsD8xMwOoZExyJ9BrLjTJSn2UAsPFzvIsQdfHFPDHkJplVh7iLGPHH/gsode6WEo24WvjKOWXfQoGyhJN6N4FFOCAVqdySY= - + eJyNVb1Ow0AMtioVdUIk0EiV4BEYgQkeBmZ2FjaQeAB4FdIdFCidClX6k4mlIqVdQEJMiHMb93yur40li7vj/H3+bF8K4FovAHiK7H5s1rnxScOeTRtQ2nx3fwxmxnieizXy8Ji/7XI8Mr8kmK81Le+hG7u5U44jDVyeYcHh00I5POwCPO6ux8d7EOr/SyJdy011vn8zsd0SHHhP9oT2rcjVgvpIy5XhuTZ+a/y8AvBSB/jesNq4xtOqWyeuAS33zBjZnYm/rNg98qE2TaPse8xwfH3pmtw77Bzz2t9b1kk2Cty5jCO779RdLciRGr8X3o7sPJCdbQFcVJfvojfZeuDpPb7V4xrASQmf6QxszbR3KetFPG2RN8UPxfmXZ3Z5DPZe4/koHPlGgR8nNxifDXc/ZvuUxUoeyUczR7lNBC7nGXtyShQ9q7iIj3LOBI+miev5LXydLswLnbAkZo/p4fXGt4AzzflWcSEmxb+GtiarLGZ1l9p8daQ6ZUptSBuf05bAma7hyj34vl7QnCXit7EvvhWcC2vO+03Y/QLLN2NxEctx+TdmEFku3m85V9y4Luwf9QTfZ8owZxrFrCzqHOp6eh4dTZGvZlQD3g/eF222+FmsYGcCi3Nlnnpp80a5LWol7mg5c9y+8h7p74H5Rh8WflSbc9CZnEEZ+w939yQl - + eJzFVVsKwkAMXIXS/guC4D28mJ7QG+jXSlvQk9ilBsJ2s500Aeenj3RnMpNAQ5gxnIIK/fT9eCjXElcv8CE671bXyxbsOtt5bV6Ip0+7zA7RuTYh3BrM076TZ+OF+3H5TpsXx/M8X8lnwqOgQUj+LHr/hLX3/DzCZ9HkuxSn+1fl2crPYeWtgXPnOh6eOJek4wELp2YnKJNSNkheazpRqCPc+f6gvrbMWeOjxu25Y8Tjvbc071zHwoVyIGdKPfJe40rNG5bsL7//uuT7C6IoWX0= - + eJxjYBgFo2AUDAbQIjD07bglSR9/jIJRMApGwShgYAAAUygCsA== - + eJzdlNENACEIQ53C/VdgQx1AoJRqLteED3OhT6qnzTFsVyabmvoKp8tC9Ze8XpzHiRWxT99YZX7ZmmWqPCr5M3c46kfy78wazXM7wxtSnw/LUUjxn1cZXl6eF8Lp3C+0x3u7UHXmYLxQBjtPlaHab8TIepA9KqrivwCLg9Kq @@ -213,9 +213,9 @@ eJxjYBgFo2AUDAawUWzo2wEynx7+GAWjYBSMglHAwAAA3vsDHQ== - + - eJztwQENAAAAwqD3T20ON6AAAHgzCcQAAQ== + eJxjYBgFo2AUjALqgFuSA+2CUTAKRsEoGDkAADcSAPQ= diff --git a/AndorsTrail/res/xml/stoutford_se.tmx b/AndorsTrail/res/xml/stoutford_se.tmx index 96775a789..84b8903f0 100644 --- a/AndorsTrail/res/xml/stoutford_se.tmx +++ b/AndorsTrail/res/xml/stoutford_se.tmx @@ -1,5 +1,5 @@ - + @@ -183,27 +183,27 @@ - + - eJzbyMnAsBEPluMiDeMzCxfeLYyK6WY/VP1pYVRMFfuB7E0E8DGo+iBpBoZgKA6RJi8M0fFFoNmXiMAgtYlAO5OgOBnNfvS4wYep4W50jB43+DCpZi9noq39hNIIOfYHIaUTetiPnjYTkdIJoXRLDfuxpc0dYoTTLbXspwQTsn8Fje3X5cKOYX6ntf3IGL2sgNk/DQ3Tyn70vAKzHxumhTvQ8wo++0F4JYVuWI5mBiiv/OZE5BVc4Y8eDvgwIfvxpS9c/l9JIFywxRU2TEgdTBwA2axxSQ== + eJy9lDEOwjAMRSO2du1YiRtwmcIFCnfiCqVjYWRnYYLrsJBIiUi/HJu2cYcnVa3l5zh2h8KYgWFbToPLleJejVnN7+Of1Zgsfvt8FXj4+KY2Zu851PN6iLxs7vcfuNjWOo+eE/jxbjhy1I3g3XBMzd1tdP3SjMzxN9GcrOHH2WyjOZHmNoefms0b8y23fwmS/6Ls35U04eza/hj8VwT/GdDy464EP4VGHbgrnN/RL6yhgxxuVz7Fb1dS/cc+cEh+br5S5++FvlB3RSHFhfdfjGFxNw== - + eJytVclKA0EQbUbG5aKZUUdGBvQT/AGXP9CrB0XwJHjxoAfxJwQlHyK4gBcXNNEQEMXtIHgJJIoInvQg1rO76EpnJhr0QVPTXd31qmvpUUqpaqxULbZyqlOpnUhLP2xtyLMngfoG22WUDMdHqFIx9w/8sMG8R4a7d1CpPhr9g3ofcE0+xp7+Zjnu/53/J6zmtJwnGRHvW7uWGJOGf4ZsjbU4ZlvkR3zA2dZh+QHY4PwBXZ79/uxtXAOeA3t2orORs0D6W7MH+k3P5uiV1m9obPhaBxvTvvWHgXl3X/0a520+Z/mRh7tAcwKnRvKdOP9clyeR9ZH5F/zGO7iQ/rn8bWH6qBLHmdMbOAMfi4J/SfDzHR8SXSuQsVev/y3/s4gLehFznCmI3GC+buJ/RFzHNDro+yXRtfJi+Fm32AI/A70n7z/q1DD7c0n2rxLtC+oDtTIQ6jnr1ug7F/6Of5n8XDG+bkd67Eb2O20u13eb6HlPM/7zWNe+zL8ruV6LKW9oReQP4JquiP6b+4H/0cQKNg9oHArukuG5J3u1INtH911nFDPeH67XEdO/NVEL/Hbkac8QrQ87/4ay4XF9BbbEXMYljdt9Txj8L+K45L3s+16LnDyJ/4v0CfnNi57gNx49tJ/otb2UON0J/8+CepvlJjlwJd+jJ7T3R98CpURzfzi9mOWT1D+KM7hfIaU+GHjn8iLe6NtTJz+3Yv5ubF8IjrQaAWScsva7+xh8R+i+ADys5xs= - + eJxjYCAeZAiQoBgIbkoyMNwC4s2SED6zFAMDixSqmofsCLaBCIR+xM5AN8DIgSnGhEWMVuCWJKbYYTH8eu4JU89+WBwhg0tQ+x+SGA/kxBs2/8PARxLN+0SG/dj8T0/79+DxP7a0eRlP2iAn3eLzPzaAL20SSrcwkAIsR9JILEtg4BIeO/DJIQPkMIf5H51GB6SGE7EAZOZGIN6EZDd6msDlRlq5CRvYB7UH3a3obsQGSC1H0M3E5V9i3YAtH5HqBhDYh8Mt5MbJVCb88vjyOjY3EmO3LBN+u6cTcBM9ALH+Jhcg+x0AK8hU/w== - + eJzFk1sOwCAIBD1F738Fb9j0w4QQ6i4LrSSkD7UzYJ3XGDPIJ9Z1hX+Owq6tJMtj+fYd41nlq56Rr9K7LN/f23kKF3m8ra3WH30H8VFvVD4K1Lu/+Nn60Zha/24fO/nZs6IEy2fPcNa3k591VZmKgx/v5Gddd//y13zG7ZTHif1g8wav+Q9b - + @@ -265,7 +265,7 @@ - + @@ -275,5 +275,5 @@ - + diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailApplication.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailApplication.java index 68f66b2de..f5b106fd7 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailApplication.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/AndorsTrailApplication.java @@ -30,8 +30,8 @@ public final class AndorsTrailApplication extends Application { public static final boolean DEVELOPMENT_DEBUGMESSAGES = false; public static final boolean DEVELOPMENT_INCOMPATIBLE_SAVEGAMES = DEVELOPMENT_DEBUGRESOURCES || DEVELOPMENT_DEBUGBUTTONS || DEVELOPMENT_FASTSPEED; public static final int DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION = 999; - public static final int CURRENT_VERSION = DEVELOPMENT_INCOMPATIBLE_SAVEGAMES ? DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION : 51; - public static final String CURRENT_VERSION_DISPLAY = "0.7.9"; + public static final int CURRENT_VERSION = DEVELOPMENT_INCOMPATIBLE_SAVEGAMES ? DEVELOPMENT_INCOMPATIBLE_SAVEGAME_VERSION : 52; + public static final String CURRENT_VERSION_DISPLAY = "0.7.10"; public static final boolean IS_RELEASE_VERSION = !CURRENT_VERSION_DISPLAY.matches(".*[a-d].*"); private final AndorsTrailPreferences preferences = new AndorsTrailPreferences(); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/Dialogs.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/Dialogs.java index 216b4ad19..12c0b68e1 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/Dialogs.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/Dialogs.java @@ -4,13 +4,18 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import android.*; +import android.Manifest; +import android.annotation.TargetApi; import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnDismissListener; import android.content.Intent; +import android.content.pm.PackageManager; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.View; @@ -106,7 +111,7 @@ public final class Dialogs { if (!params.containsKey("x")) return null; int x = params.getInt("x"); int y = params.getInt("y"); - return world.model.currentMap.getMonsterAt(x, y); + return world.model.currentMaps.map.getMonsterAt(x, y); } public static void showMonsterEncounter(final MainActivity currentActivity, final ControllerContext context, final Monster monster) { @@ -318,26 +323,47 @@ public final class Dialogs { showDialogAndPause(d, controllerContext); } - public static void showNewVersion(final Activity currentActivity) { + public static void showNewVersion(final Activity currentActivity, final OnDismissListener onDismiss) { // new AlertDialog.Builder(new ContextThemeWrapper(currentActivity, R.style.AndorsTrailStyle)) // .setTitle(R.string.dialog_newversion_title) // .setMessage(R.string.dialog_newversion_message) // .setNeutralButton(android.R.string.ok, null) // .show(); + String text = currentActivity.getResources().getString(R.string.dialog_newversion_message); + + if (!hasPermissions(currentActivity)) { + text += currentActivity.getResources().getString(R.string.dialog_newversion_permission_information); + } + final Dialog d = CustomDialogFactory.createDialog(currentActivity, currentActivity.getResources().getString(R.string.dialog_newversion_title), null, - currentActivity.getResources().getString(R.string.dialog_newversion_message), + text, null, true); - CustomDialogFactory.addDismissButton(d, android.R.string.ok); - + CustomDialogFactory.setDismissListener(d, new OnDismissListener() { + @Override + public void onDismiss(DialogInterface arg0) { + if (onDismiss != null) onDismiss.onDismiss(arg0); + } + }); CustomDialogFactory.show(d); } + @TargetApi(23) + private static boolean hasPermissions(final Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (activity.getApplicationContext().checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED + || activity.getApplicationContext().checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + return false; + } + } + return true; + } + public static boolean showSave(final Activity mainActivity, final ControllerContext controllerContext, final WorldContext world) { if (world.model.uiSelections.isInCombat) { Toast.makeText(mainActivity, R.string.menu_save_saving_not_allowed_in_combat, Toast.LENGTH_SHORT).show(); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ConversationActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ConversationActivity.java index d80d928ac..0aaee3fdf 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ConversationActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ConversationActivity.java @@ -7,6 +7,7 @@ import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.Color; +import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -42,6 +43,7 @@ import com.gpl.rpg.AndorsTrail.model.item.Loot; import com.gpl.rpg.AndorsTrail.model.quest.Quest; import com.gpl.rpg.AndorsTrail.model.quest.QuestLogEntry; import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress; +import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection; import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager; import com.gpl.rpg.AndorsTrail.util.ThemeHelper; @@ -76,11 +78,15 @@ public final class ConversationActivity setContentView(R.layout.conversation); + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + setFinishOnTouchOutside(false); + } + replyGroup = new RadioGroup(this); replyGroup.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, ListView.LayoutParams.WRAP_CONTENT)); statementList = (ListView) findViewById(R.id.conversation_statements); statementList.addFooterView(replyGroup); - listAdapter = new StatementContainerAdapter(this, conversationHistory, world.tileManager); + listAdapter = new StatementContainerAdapter(this, conversationHistory, world.tileManager, world.model.currentMaps.tiles); statementList.setAdapter(listAdapter); nextButton = (Button) findViewById(R.id.conversation_next); @@ -344,10 +350,12 @@ public final class ConversationActivity private static final class StatementContainerAdapter extends ArrayAdapter { private final TileManager tileManager; + private final TileCollection tiles; - public StatementContainerAdapter(Context context, ArrayList items, TileManager tileManager) { + public StatementContainerAdapter(Context context, ArrayList items, TileManager tileManager, TileCollection tiles) { super(context, 0, items); this.tileManager = tileManager; + this.tiles = tiles; } @Override @@ -362,7 +370,7 @@ public final class ConversationActivity if (statement.hasActor()) { final Resources res = getContext().getResources(); if (statement.isPlayerActor) tileManager.setImageViewTileForPlayer(res, tv, statement.iconID); - else tileManager.setImageViewTileForMonster(res, tv, statement.iconID); + else tileManager.setImageViewTileForMonster(res, tv, statement.iconID, tiles); tv.setText(statement.actorName + ": " + statement.text, BufferType.SPANNABLE); Spannable sp = (Spannable) tv.getText(); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/DisplayWorldMapActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/DisplayWorldMapActivity.java index 50410e5d8..4c0904ec0 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/DisplayWorldMapActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/DisplayWorldMapActivity.java @@ -93,7 +93,7 @@ public final class DisplayWorldMapActivity extends AndorsTrailBaseActivity { } WorldMapSegment segment = world.maps.worldMapSegments.get(worldMapSegmentName); - map = segment.maps.get(world.model.currentMap.name); + map = segment.maps.get(world.model.currentMaps.map.name); if (map == null) { this.finish(); return; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MainActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MainActivity.java index 69fcc57d1..eb55c9a9d 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MainActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MainActivity.java @@ -6,6 +6,7 @@ import java.util.Collection; import android.app.Activity; import android.app.Dialog; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; @@ -304,6 +305,9 @@ public final class MainActivity t = Toast.makeText(this, msg, duration); lastToast = new WeakReference(t); } else { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && t.getView().isShown()) { + t.cancel(); + } t.setText(msg); t.setDuration(duration); } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterEncounterActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterEncounterActivity.java index bdf69ce31..846669365 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterEncounterActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterEncounterActivity.java @@ -41,7 +41,7 @@ public final class MonsterEncounterActivity extends AndorsTrailBaseActivity { TextView tv = (TextView) findViewById(R.id.monsterencounter_title); tv.setText(monster.getName()); - world.tileManager.setImageViewTile(getResources(), tv, monster); + world.tileManager.setImageViewTile(getResources(), tv, monster, world.model.currentMaps.tiles); tv = (TextView) findViewById(R.id.monsterencounter_description); tv.setText(getString(R.string.dialog_monsterencounter_message, difficulty)); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterInfoActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterInfoActivity.java index 16764b2a3..5de716a9b 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterInfoActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/MonsterInfoActivity.java @@ -79,7 +79,7 @@ public final class MonsterInfoActivity extends AndorsTrailBaseActivity { private void updateTitle(Monster monster) { monsterinfo_title.setText(monster.getName()); - world.tileManager.setImageViewTile(getResources(), monsterinfo_title, monster); + world.tileManager.setImageViewTile(getResources(), monsterinfo_title, monster, world.model.currentMaps.tiles); monsterinfo_difficulty.setText(getMonsterDifficultyResource(controllers, monster)); } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/SkillInfoActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/SkillInfoActivity.java index c438cda66..aac4f63b4 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/SkillInfoActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/SkillInfoActivity.java @@ -148,6 +148,7 @@ public final class SkillInfoActivity extends AndorsTrailBaseActivity { case fightstyleDualWield: return R.string.skill_title_fightstyle_dualwield; case fightstyle2hand: return R.string.skill_title_fightstyle_2hand; case fightstyleWeaponShield: return R.string.skill_title_fightstyle_weapon_shield; + case fightstyleUnarmedUnarmored: return R.string.skill_title_fightstyle_unarmed_unarmored; case specializationDualWield: return R.string.skill_title_specialization_dualwield; case specialization2hand: return R.string.skill_title_specialization_2hand; case specializationWeaponShield: return R.string.skill_title_specialization_weapon_shield; @@ -198,6 +199,12 @@ public final class SkillInfoActivity extends AndorsTrailBaseActivity { case fightstyleDualWield: return res.getString(R.string.skill_longdescription_fightstyle_dualwield, SkillCollection.DUALWIELD_EFFICIENCY_LEVEL0, SkillCollection.DUALWIELD_EFFICIENCY_LEVEL1, SkillCollection.DUALWIELD_LEVEL1_OFFHAND_AP_COST_PERCENT, SkillCollection.DUALWIELD_EFFICIENCY_LEVEL2); case fightstyle2hand: return res.getString(R.string.skill_longdescription_fightstyle_2hand, SkillCollection.PER_SKILLPOINT_INCREASE_FIGHTSTYLE_2HAND_DMG_PERCENT); case fightstyleWeaponShield: return res.getString(R.string.skill_longdescription_fightstyle_weapon_shield, SkillCollection.PER_SKILLPOINT_INCREASE_FIGHTSTYLE_WEAPON_AC_PERCENT, SkillCollection.PER_SKILLPOINT_INCREASE_FIGHTSTYLE_SHIELD_BC_PERCENT); + case fightstyleUnarmedUnarmored: return res.getString(R.string.skill_longdescription_fightstyle_unarmed_unarmored, + SkillCollection.PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_AC, + SkillCollection.PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_BC, + SkillCollection.PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_DR, + SkillCollection.PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_DMG_MAX, + SkillCollection.PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_CM_PERCENT); case specializationDualWield: return res.getString(R.string.skill_longdescription_specialization_dualwield, SkillCollection.PER_SKILLPOINT_INCREASE_SPECIALIZATION_DUALWIELD_AC_PERCENT, SkillCollection.PER_SKILLPOINT_INCREASE_SPECIALIZATION_DUALWIELD_BC_PERCENT); case specialization2hand: return res.getString(R.string.skill_longdescription_specialization_2hand, SkillCollection.PER_SKILLPOINT_INCREASE_SPECIALIZATION_2HAND_DMG_PERCENT, SkillCollection.PER_SKILLPOINT_INCREASE_SPECIALIZATION_2HAND_AC_PERCENT); case specializationWeaponShield: return res.getString(R.string.skill_longdescription_specialization_weapon_shield, SkillCollection.PER_SKILLPOINT_INCREASE_SPECIALIZATION_WEAPON_AC_PERCENT, SkillCollection.PER_SKILLPOINT_INCREASE_SPECIALIZATION_WEAPON_DMG_PERCENT); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/StartScreenActivity.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/StartScreenActivity.java index bd625bbb6..e15976847 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/StartScreenActivity.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/StartScreenActivity.java @@ -10,9 +10,13 @@ import com.gpl.rpg.AndorsTrail.activity.fragment.StartScreenActivity_NewGame.Gam import com.gpl.rpg.AndorsTrail.resource.tiles.TileManager; import com.gpl.rpg.AndorsTrail.util.ThemeHelper; import com.gpl.rpg.AndorsTrail.view.CloudsAnimatorView; +import com.gpl.rpg.AndorsTrail.view.CustomDialogFactory; import android.Manifest; import android.annotation.TargetApi; +import android.app.Activity; +import android.app.Dialog; +import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Resources; @@ -109,34 +113,30 @@ public final class StartScreenActivity extends AndorsTrailBaseFragmentActivity i toggleUiVisibility(); app.getWorldSetup().startResourceLoader(res); - - checkAndRequestPermissions(); - } - - private static final int READ_EXTERNAL_STORAGE_REQUEST=1; - private static final int WRITE_EXTERNAL_STORAGE_REQUEST=2; - - @TargetApi(23) - private void checkAndRequestPermissions() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (getApplicationContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - this.requestPermissions(new String[] {Manifest.permission.READ_EXTERNAL_STORAGE}, READ_EXTERNAL_STORAGE_REQUEST); - } - if (getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - this.requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_REQUEST); - } - } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) { - Toast.makeText(this, R.string.storage_permissions_mandatory, Toast.LENGTH_LONG).show(); - ((AndorsTrailApplication)getApplication()).discardWorld(); - finish(); + + final Dialog d = CustomDialogFactory.createDialog(this, + getResources().getString(R.string.dialog_permission_information_title), + getResources().getDrawable(android.R.drawable.ic_dialog_info), + getResources().getString(R.string.dialog_permission_information), + null, + true); + final Activity activity = this; + CustomDialogFactory.addDismissButton(d, android.R.string.ok); + CustomDialogFactory.setDismissListener(d, new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + StartScreenActivity_MainMenu.checkAndRequestPermissions(activity); + } + }); + CustomDialogFactory.show(d); } } - + private void toggleUiVisibility() { ui_visible = !ui_visible; int visibility = ui_visible ? View.VISIBLE : View.GONE; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/fragment/HeroinfoActivity_Quests.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/fragment/HeroinfoActivity_Quests.java index ece9d03f7..c88057814 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/fragment/HeroinfoActivity_Quests.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/fragment/HeroinfoActivity_Quests.java @@ -116,43 +116,43 @@ public final class HeroinfoActivity_Quests extends Fragment { groupList.clear(); childList.clear(); - for (Quest q : world.quests.getAllQuests()) { + for (String questProgressID : player.getAllQuestProgressIDs()) { + Quest q = world.quests.getQuest(questProgressID); + if (q == null) continue; // This should not happen if (!q.showInLog) continue; // Do not show - if (player.hasAnyQuestProgress(q.questID)) { - boolean isCompleted = q.isCompleted(player); + boolean isCompleted = q.isCompleted(player); - int v = world.model.uiSelections.selectedQuestFilter; - if (v == 0) { // Hide completed quests - if (isCompleted) continue; - } else if (v == 1) { // Include completed quests - // Always show. - } else if (v == 2) { // Only completed quests - if (!isCompleted) continue; - } - - int statusResId; - if (isCompleted) { - statusResId = R.string.questlog_queststatus_completed; - } else { - statusResId = R.string.questlog_queststatus_inprogress; - } - - Map item = new HashMap(); - item.put(mn_questName, q.name); - item.put(mn_questStatus, getString(R.string.questlog_queststatus, getString(statusResId))); - groupList.add(item); - - List> logItemList = new ArrayList>(); - for (QuestLogEntry e : q.stages) { - if (e.logtext.length() <= 0) continue; // Do not show if displaytext is empty. - if (player.hasExactQuestProgress(q.questID, e.progress)) { - item = new HashMap(); - item.put(mn_logText, e.logtext); - logItemList.add(item); - } - } - childList.add(logItemList); + int v = world.model.uiSelections.selectedQuestFilter; + if (v == 0) { // Active quests + if (isCompleted) continue; + } else if (v == 1) { // All quests + // Always show. + } else if (v == 2) { // Completed quests + if (!isCompleted) continue; } + + int statusResId; + if (isCompleted) { + statusResId = R.string.questlog_queststatus_completed; + } else { + statusResId = R.string.questlog_queststatus_inprogress; + } + + Map item = new HashMap(); + item.put(mn_questName, q.name); + item.put(mn_questStatus, getString(R.string.questlog_queststatus, getString(statusResId))); + groupList.add(item); + + List> logItemList = new ArrayList>(); + for (QuestLogEntry e : q.stages) { + if (e.logtext.length() <= 0) continue; // Do not show if displaytext is empty. + if (player.hasExactQuestProgress(q.questID, e.progress)) { + item = new HashMap(); + item.put(mn_logText, e.logtext); + logItemList.add(item); + } + } + childList.add(logItemList); } questlog_contents_adapter.notifyDataSetChanged(); } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/fragment/StartScreenActivity_MainMenu.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/fragment/StartScreenActivity_MainMenu.java index 72761c541..a85b0284f 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/fragment/StartScreenActivity_MainMenu.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/fragment/StartScreenActivity_MainMenu.java @@ -1,11 +1,15 @@ package com.gpl.rpg.AndorsTrail.activity.fragment; +import android.Manifest; import android.annotation.SuppressLint; +import android.annotation.TargetApi; import android.app.Activity; import android.app.Dialog; +import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; +import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; @@ -140,6 +144,12 @@ public class StartScreenActivity_MainMenu extends Fragment { } else if (AndorsTrailApplication.DEVELOPMENT_FORCE_CONTINUEGAME) { continueGame(false, Savegames.SLOT_QUICKSAVE, null); } + + // if it is a new version we first fire a welcome screen in onResume + // and afterwards check the permissions + if (!isNewVersion()) { + checkAndRequestPermissions(getActivity()); + } return root; } @@ -171,13 +181,34 @@ public class StartScreenActivity_MainMenu extends Fragment { setButtonState(playerName, displayInfo, iconID, isDead); if (isNewVersion()) { - Dialogs.showNewVersion(getActivity()); + Dialogs.showNewVersion(getActivity(), new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface arg0) { + setCurrentVersionForVersionCheck(); + checkAndRequestPermissions(getActivity()); + } + }); } boolean hasSavegames = !Savegames.getUsedSavegameSlots().isEmpty(); startscreen_load.setEnabled(hasSavegames); } - + + private static final int READ_EXTERNAL_STORAGE_REQUEST=1; + private static final int WRITE_EXTERNAL_STORAGE_REQUEST=2; + + @TargetApi(23) + public static void checkAndRequestPermissions(final Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (activity.getApplicationContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + activity.requestPermissions(new String[] {Manifest.permission.READ_EXTERNAL_STORAGE}, READ_EXTERNAL_STORAGE_REQUEST); + } + if (activity.getApplicationContext().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + activity.requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_REQUEST); + } + } + } + @Override public void onAttach(Activity activity) { super.onAttach(activity); @@ -246,17 +277,21 @@ public class StartScreenActivity_MainMenu extends Fragment { CustomDialogFactory.show(d); } - + + private static final String versionCheck = "lastversion"; private boolean isNewVersion() { - final String v = "lastversion"; SharedPreferences s = getActivity().getSharedPreferences(Constants.PREFERENCE_MODEL_LASTRUNVERSION, Activity.MODE_PRIVATE); - int lastversion = s.getInt(v, 0); + int lastversion = s.getInt(versionCheck, 0); if (lastversion >= AndorsTrailApplication.CURRENT_VERSION) return false; - Editor e = s.edit(); - e.putInt(v, AndorsTrailApplication.CURRENT_VERSION); - e.commit(); return true; } + + private void setCurrentVersionForVersionCheck() { + SharedPreferences s = getActivity().getSharedPreferences(Constants.PREFERENCE_MODEL_LASTRUNVERSION, Activity.MODE_PRIVATE); + Editor e = s.edit(); + e.putInt(versionCheck, AndorsTrailApplication.CURRENT_VERSION); + e.commit(); + } @Override diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ActorStatsController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ActorStatsController.java index 0f128c0aa..b6a488c02 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ActorStatsController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ActorStatsController.java @@ -272,27 +272,39 @@ public final class ActorStatsController { actor.damagePotential.addToMax(effects.increaseMaxDamage * multiplier); actor.blockChance += effects.increaseBlockChance * multiplier; actor.damageResistance += effects.increaseDamageResistance * multiplier; - - if (actor.attackChance < 0) actor.attackChance = 0; - if (actor.damagePotential.max < 0) actor.damagePotential.set(0, 0); } public void recalculatePlayerStats(Player player) { + player.weaponDamage.set(0,0); player.resetStatsToBaseTraits(); player.recalculateLevelExperience(); controllers.itemController.applyInventoryEffects(player); controllers.skillController.applySkillEffects(player); applyEffectsFromCurrentConditions(player); ItemController.recalculateHitEffectsFromWornItems(player); + ItemController.applyDamageModifier(player); capActorHealthAtMax(player); capActorAPAtMax(player); + lowCapActorAttackChance(player); + lowCapActorDamagePotential(player); } public void recalculateMonsterCombatTraits(Monster monster) { monster.resetStatsToBaseTraits(); applyEffectsFromCurrentConditions(monster); capActorHealthAtMax(monster); capActorAPAtMax(monster); + lowCapActorAttackChance(monster); + lowCapActorDamagePotential(monster); } + + private void lowCapActorAttackChance(Actor actor) { + if (actor.attackChance < 0) actor.attackChance = 0; + } + + private void lowCapActorDamagePotential(Actor actor) { + if (actor.damagePotential.max < 0) actor.damagePotential.set(0, 0); + } + private void recalculateActorCombatTraits(Actor actor) { if (actor.isPlayer) recalculatePlayerStats((Player) actor); else recalculateMonsterCombatTraits((Monster) actor); @@ -545,6 +557,11 @@ public final class ActorStatsController { } } + public void addPlayerWeaponDamage(Player player, int increaseMinDamage, int increaseMaxDamage) { + player.weaponDamage.add(increaseMinDamage, true); + player.weaponDamage.addToMax(increaseMaxDamage); + } + public static enum LevelUpSelection { health ,attackChance diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/CombatController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/CombatController.java index d6bbac491..75706b472 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/CombatController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/CombatController.java @@ -25,6 +25,8 @@ import com.gpl.rpg.AndorsTrail.model.map.MonsterSpawnArea; import com.gpl.rpg.AndorsTrail.resource.VisualEffectCollection; import com.gpl.rpg.AndorsTrail.util.Coord; +import static java.lang.Math.max; + public final class CombatController implements VisualEffectCompletedCallback { private final ControllerContext controllers; private final WorldContext world; @@ -109,10 +111,10 @@ public final class CombatController implements VisualEffectCompletedCallback { } public void setCombatSelection(Coord p) { - Monster m = world.model.currentMap.getMonsterAt(p); + Monster m = world.model.currentMaps.map.getMonsterAt(p); if (m != null) { setCombatSelection(m, p); - } else if (world.model.currentTileMap.isWalkable(p)) { + } else if (world.model.currentMaps.tileMap.isWalkable(p)) { setCombatSelection(null, p); } } @@ -128,7 +130,7 @@ public final class CombatController implements VisualEffectCompletedCallback { public boolean canExitCombat() { return getAdjacentAggressiveMonster() == null; } private Monster getAdjacentAggressiveMonster() { - return MovementController.getAdjacentAggressiveMonster(world.model.currentMap, world.model.player); + return MovementController.getAdjacentAggressiveMonster(world.model.currentMaps.map, world.model.player); } public void executeMoveAttack(int dx, int dy) { @@ -155,7 +157,7 @@ public final class CombatController implements VisualEffectCompletedCallback { private void executeFlee(int dx, int dy) { // avoid monster fields when fleeing if (!controllers.movementController.findWalkablePosition(dx, dy, AndorsTrailPreferences.MOVEMENTAGGRESSIVENESS_DEFENSIVE)) return; - Monster m = world.model.currentMap.getMonsterAt(world.model.player.nextPosition); + Monster m = world.model.currentMaps.map.getMonsterAt(world.model.player.nextPosition); if (m != null) return; executeCombatMove(world.model.player.nextPosition); } @@ -198,11 +200,11 @@ public final class CombatController implements VisualEffectCompletedCallback { public void playerKilledMonster(Monster killedMonster) { final Player player = world.model.player; - Loot loot = world.model.currentMap.getBagOrCreateAt(killedMonster.position); + Loot loot = world.model.currentMaps.map.getBagOrCreateAt(killedMonster.position); killedMonster.createLoot(loot, player); - controllers.monsterSpawnController.remove(world.model.currentMap, killedMonster); - controllers.effectController.addSplatter(world.model.currentMap, killedMonster); + controllers.monsterSpawnController.remove(world.model.currentMaps.map, killedMonster); + controllers.effectController.addSplatter(world.model.currentMaps.map, killedMonster); controllers.actorStatsController.addActorAP(player, player.getSkillLevel(SkillCollection.SkillID.cleave) * SkillCollection.PER_SKILLPOINT_INCREASE_CLEAVE_AP); controllers.actorStatsController.addActorHealth(player, player.getSkillLevel(SkillCollection.SkillID.eater) * SkillCollection.PER_SKILLPOINT_INCREASE_EATER_HEALTH); @@ -216,7 +218,7 @@ public final class CombatController implements VisualEffectCompletedCallback { controllers.actorStatsController.applyOnDeathEffectsToPlayer(player, killedMonster); if (!loot.hasItemsOrGold()) { - world.model.currentMap.removeGroundLoot(loot); + world.model.currentMaps.map.removeGroundLoot(loot); } else if (world.model.uiSelections.isInCombat) { killedMonsterBags.add(loot); } @@ -305,7 +307,7 @@ public final class CombatController implements VisualEffectCompletedCallback { private void beginMonsterTurn(boolean isFirstRound) { controllers.actorStatsController.setActorMinAP(world.model.player); world.model.uiSelections.isPlayersCombatTurn = false; - for (MonsterSpawnArea a : world.model.currentMap.spawnAreas) { + for (MonsterSpawnArea a : world.model.currentMaps.map.spawnAreas) { for (Monster m : a.monsters) { controllers.actorStatsController.setActorMaxAP(m); } @@ -323,7 +325,7 @@ public final class CombatController implements VisualEffectCompletedCallback { if (shouldAttackWithMonsterInCombat(currentActiveMonster, playerPosition)) return MonsterAction.attack; } - for (MonsterSpawnArea a : world.model.currentMap.spawnAreas) { + for (MonsterSpawnArea a : world.model.currentMaps.map.spawnAreas) { for (Monster m : a.monsters) { if (!m.isAgressive(world.model.player)) continue; @@ -387,7 +389,7 @@ public final class CombatController implements VisualEffectCompletedCallback { } final Monster movingMonster = currentActiveMonster; - controllers.monsterMovementController.moveMonsterToNextPositionDuringCombat(currentActiveMonster, world.model.currentMap, new VisualEffectController.VisualEffectCompletedCallback(){ + controllers.monsterMovementController.moveMonsterToNextPositionDuringCombat(currentActiveMonster, world.model.currentMaps.map, new VisualEffectController.VisualEffectCompletedCallback(){ @Override public void onVisualEffectCompleted(int callbackValue) { combatActionListeners.onMonsterMovedDuringCombat(movingMonster); @@ -484,13 +486,29 @@ public final class CombatController implements VisualEffectCompletedCallback { if (target.isImmuneToCriticalHits()) return false; return true; } - private static float getAverageDamagePerHit(Actor attacker, Actor target) { - float result = (float) (getAttackHitChance(attacker, target)) * attacker.getDamagePotential().average() / 100; - if (hasCriticalAttack(attacker, target)) { - result += (float) attacker.getEffectiveCriticalChance() * result * attacker.getCriticalMultiplier() / 100; + + // see this post for explenations about the calculation: https://andorstrail.com/viewtopic.php?f=3&t=6661 + // if you change code here make sure to run the tests in CombatControllerTest.java + public static float getAverageDamagePerHit(final Actor attacker, final Actor target) { + final int numPossibleOutcomes = attacker.getDamagePotential().max - attacker.getDamagePotential().current + 1; + float avgNonCriticalDamage = 0; + for (int n = 0; n < numPossibleOutcomes; n++) { + avgNonCriticalDamage += max(0, (float) n + attacker.getDamagePotential().current - target.getDamageResistance()) / numPossibleOutcomes; } - result -= target.getDamageResistance(); - return result; + + float avgCriticalDamage = 0; + float effectiveCriticalChance = 0; + if (hasCriticalAttack(attacker, target)) { + effectiveCriticalChance = attacker.getEffectiveCriticalChance(); + } + if (effectiveCriticalChance > 0) { + for (int n = 0; n < numPossibleOutcomes; n++) { + avgCriticalDamage += max(0, Math.floor((n + attacker.getDamagePotential().current) * attacker.getCriticalMultiplier()) - target.getDamageResistance()) / numPossibleOutcomes; + } + } + + float avgDamagePerSuccessfulStrike = (1 - effectiveCriticalChance / 100) * avgNonCriticalDamage + effectiveCriticalChance * avgCriticalDamage / 100; + return (float)getAttackHitChance(attacker, target) * avgDamagePerSuccessfulStrike / 100; } private static float getAverageDamagePerTurn(Actor attacker, Actor target) { return getAverageDamagePerHit(attacker, target) * attacker.getAttacksPerTurn(); @@ -577,7 +595,7 @@ public final class CombatController implements VisualEffectCompletedCallback { world.model.worldData.tickWorldTime(); controllers.gameRoundController.resetRoundTimers(); controllers.actorStatsController.applyConditionsToPlayer(world.model.player, false); - controllers.actorStatsController.applyConditionsToMonsters(world.model.currentMap, true); + controllers.actorStatsController.applyConditionsToMonsters(world.model.currentMaps.map, true); } public void monsterSteppedOnPlayer(Monster m) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/CombatControllerTest.java.txt b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/CombatControllerTest.java.txt new file mode 100644 index 000000000..6c47080f3 --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/CombatControllerTest.java.txt @@ -0,0 +1,30 @@ +package com.gpl.rpg.AndorsTrail.controller; + +import com.gpl.rpg.AndorsTrail.model.actor.Actor; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class CombatControllerTest { + @Test + public void getAverageDamagePerHit() throws Exception { + Actor attacker = new Actor(null, false, false); + attacker.attackChance = 100; + attacker.damagePotential.set(5, 3); + + Actor target = new Actor(null, false, false); + target.damageResistance = 3; + target.blockChance = 50; + + float averageDamagePerHit = CombatController.getAverageDamagePerHit(attacker, target); + assertEquals(0.5, averageDamagePerHit, 0.01); + + attacker.criticalSkill = 30; + attacker.criticalMultiplier = 2.5f; + + averageDamagePerHit = CombatController.getAverageDamagePerHit(attacker, target); + assertEquals(1.038, averageDamagePerHit, 0.01); + } + +} \ No newline at end of file diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java index 695322db3..55c3322c2 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java @@ -130,7 +130,7 @@ public final class ConversationController { private void changeMapFilter(Resources res, String mapName, String effectID) { PredefinedMap map = findMapForScriptEffect(mapName); map.currentColorFilter = effectID; - if (world.model.currentMap == map) { + if (world.model.currentMaps.map == map) { controllers.mapController.applyCurrentMapReplacements(res, true); } } @@ -141,7 +141,7 @@ public final class ConversationController { } private PredefinedMap findMapForScriptEffect(String mapName) { - if (mapName == null) return world.model.currentMap; + if (mapName == null) return world.model.currentMaps.map; return world.maps.findPredefinedMap(mapName); } @@ -153,8 +153,8 @@ public final class ConversationController { private void spawnAll(String mapName, String areaId) { PredefinedMap map = findMapForScriptEffect(mapName); LayeredTileMap tileMap = null; - if (map == world.model.currentMap) { - tileMap = world.model.currentTileMap; + if (map == world.model.currentMaps.map) { + tileMap = world.model.currentMaps.tileMap; } for (MonsterSpawnArea area : map.spawnAreas) { if (!area.areaID.equals(areaId)) continue; @@ -174,12 +174,12 @@ public final class ConversationController { private void addAlignmentReward(Player player, String faction, int delta) { player.addAlignment(faction, delta); - MovementController.refreshMonsterAggressiveness(world.model.currentMap, world.model.player); + MovementController.refreshMonsterAggressiveness(world.model.currentMaps.map, world.model.player); } private void setAlignmentReward(Player player, String faction, int delta) { player.setAlignment(faction, delta); - MovementController.refreshMonsterAggressiveness(world.model.currentMap, world.model.player); + MovementController.refreshMonsterAggressiveness(world.model.currentMaps.map, world.model.player); } private void addQuestProgressReward(Player player, String questID, int questProgress, ScriptEffectResult result) { @@ -241,11 +241,11 @@ public final class ConversationController { result.actorConditions.add(e); } - private static void applyReplyEffect(final WorldContext world, final Reply reply) { + private static void applyReplyEffect(final WorldContext world, final Reply reply, ControllerContext controllers) { if (!reply.hasRequirements()) return; for (Requirement requirement : reply.requires) { - requirementFulfilled(world, requirement); + requirementFulfilled(world, requirement, controllers); } } @@ -270,6 +270,7 @@ public final class ConversationController { result = player.isLatestQuestProgress(requirement.requireID, requirement.value); break; case wear: + case wearRemove: result = player.inventory.isWearing(requirement.requireID, requirement.value); break; case inventoryKeep: @@ -316,7 +317,7 @@ public final class ConversationController { return requirement.negate ? !result : result; } - public static void requirementFulfilled(WorldContext world, Requirement requirement) { + public static void requirementFulfilled(WorldContext world, Requirement requirement, ControllerContext controllers) { Player p = world.model.player; switch (requirement.requireType) { case inventoryRemove: @@ -326,6 +327,10 @@ public final class ConversationController { } else { p.inventory.removeItem(requirement.requireID, requirement.value); } + break; + case wearRemove: + controllers.itemController.removeEquippedItem(requirement.requireID, requirement.value); + break; } } @@ -357,7 +362,7 @@ public final class ConversationController { public String getCurrentPhraseID() { return currentPhraseID; } public void playerSelectedReply(final Resources res, Reply r) { - applyReplyEffect(world, r); + applyReplyEffect(world, r, controllers); proceedToPhrase(res, r.nextPhrase, true, true); } @@ -383,7 +388,7 @@ public final class ConversationController { if (currentPhrase == null) currentPhrase = new Phrase("(phrase \"" + phraseID + "\" not implemented yet)", null, null, null); } if (this.currentPhrase.switchToNPC != null) { - setCurrentNPC(world.model.currentMap.findSpawnedMonster(this.currentPhrase.switchToNPC)); + setCurrentNPC(world.model.currentMaps.map.findSpawnedMonster(this.currentPhrase.switchToNPC)); } } @@ -414,7 +419,7 @@ public final class ConversationController { if (currentPhrase.message == null) { for (Reply r : currentPhrase.replies) { if (!canSelectReply(world, r)) continue; - applyReplyEffect(world, r); + applyReplyEffect(world, r, controllers); proceedToPhrase(res, r.nextPhrase, applyScriptEffects, displayPhraseMessage); return; } @@ -440,7 +445,7 @@ public final class ConversationController { listener.onConversationEnded(); return; } - controllers.monsterSpawnController.remove(world.model.currentMap, npc); + controllers.monsterSpawnController.remove(world.model.currentMaps.map, npc); listener.onConversationEndedWithRemoval(npc); } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/GameRoundController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/GameRoundController.java index b1681c61a..698b64307 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/GameRoundController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/GameRoundController.java @@ -74,7 +74,7 @@ public final class GameRoundController implements TimedMessageTask.Callback { public void onNewFullRound() { controllers.mapController.resetMapsNotRecentlyVisited(); - controllers.actorStatsController.applyConditionsToMonsters(world.model.currentMap, true); + controllers.actorStatsController.applyConditionsToMonsters(world.model.currentMaps.map, true); controllers.actorStatsController.applyConditionsToPlayer(world.model.player, true); gameRoundListeners.onNewFullRound(); } @@ -87,19 +87,19 @@ public final class GameRoundController implements TimedMessageTask.Callback { public void onNewPlayerRound() { world.model.worldData.tickWorldTime(); controllers.actorStatsController.applyConditionsToPlayer(world.model.player, false); - controllers.actorStatsController.applySkillEffectsForNewRound(world.model.player, world.model.currentMap); - controllers.mapController.handleMapEvents(world.model.currentMap, world.model.player.position, MapObject.MapObjectEvaluationType.afterEveryRound); + controllers.actorStatsController.applySkillEffectsForNewRound(world.model.player, world.model.currentMaps.map); + controllers.mapController.handleMapEvents(world.model.currentMaps.map, world.model.player.position, MapObject.MapObjectEvaluationType.afterEveryRound); } public void onNewMonsterRound() { - controllers.actorStatsController.applyConditionsToMonsters(world.model.currentMap, false); + controllers.actorStatsController.applyConditionsToMonsters(world.model.currentMaps.map, false); } private void onNewTick() { controllers.monsterMovementController.moveMonsters(); - controllers.monsterSpawnController.maybeSpawn(world.model.currentMap, world.model.currentTileMap); + controllers.monsterSpawnController.maybeSpawn(world.model.currentMaps.map, world.model.currentMaps.tileMap); controllers.monsterMovementController.attackWithAgressiveMonsters(); - controllers.effectController.updateSplatters(world.model.currentMap); - controllers.mapController.handleMapEvents(world.model.currentMap, world.model.player.position, MapObject.MapObjectEvaluationType.continuously); + controllers.effectController.updateSplatters(world.model.currentMaps.map); + controllers.mapController.handleMapEvents(world.model.currentMaps.map, world.model.player.position, MapObject.MapObjectEvaluationType.continuously); gameRoundListeners.onNewTick(); } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ItemController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ItemController.java index 77090476c..a1336d2a9 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ItemController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ItemController.java @@ -19,6 +19,8 @@ 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 static java.lang.Math.min; + public final class ItemController { private final ControllerContext controllers; @@ -33,7 +35,7 @@ public final class ItemController { public void dropItem(ItemType type, int quantity) { 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); + world.model.currentMaps.map.itemDropped(type, quantity, world.model.player.position); } public void equipItem(ItemType type, Inventory.WearSlot slot) { @@ -175,8 +177,12 @@ public final class ItemController { // The stats for off-hand weapons will be added later in SkillController.applySkillEffectsFromFightingStyles if (SkillController.isDualWielding(mainHandItem, type)) return; } - if (type.effects_equip != null && type.effects_equip.stats != null) - controllers.actorStatsController.applyAbilityEffects(player, type.effects_equip.stats, 1); + if (type.effects_equip != null && type.effects_equip.stats != null) { + controllers.actorStatsController.applyAbilityEffects(player, type.effects_equip.stats, 1); + if (type.isWeapon()) { + controllers.actorStatsController.addPlayerWeaponDamage(player, type.effects_equip.stats.increaseMinDamage, type.effects_equip.stats.increaseMaxDamage); + } + } } public static void recalculateHitEffectsFromWornItems(Player player) { @@ -239,8 +245,8 @@ public final class ItemController { public boolean removeLootBagIfEmpty(final Loot loot) { if (loot.hasItemsOrGold()) return false; - world.model.currentMap.removeGroundLoot(loot); - controllers.mapController.mapLayoutListeners.onLootBagRemoved(world.model.currentMap, loot.position); + world.model.currentMaps.map.removeGroundLoot(loot); + controllers.mapController.mapLayoutListeners.onLootBagRemoved(world.model.currentMaps.map, loot.position); return true; // The bag was removed. } @@ -383,4 +389,41 @@ public final class ItemController { } } + public int removeEquippedItem(String itemTypeID, int count) { + int removed = 0; + final Player player = world.model.player; + for (Inventory.WearSlot slot : Inventory.WearSlot.values()) { + ItemType type = player.inventory.getItemTypeInWearSlot(slot); + if (type != null && type.id.equals(itemTypeID)) { + player.inventory.setItemTypeInWearSlot(slot, null); + controllers.actorStatsController.removeConditionsFromUnequippedItem(player, type); + controllers.actorStatsController.recalculatePlayerStats(player); + removed++; + if (removed >= count) { + break; + } + } + } + return removed; + } + public static void applyDamageModifier(Player player) { + ItemType itemType = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.weapon); + int modifier1 = -1; + int modifier2 = -1; + if (itemType != null) modifier1 = itemType.effects_equip.stats.setNonWeaponDamageModifier; + itemType = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.shield); + if (itemType != null && itemType.isWeapon()) modifier2 = itemType.effects_equip.stats.setNonWeaponDamageModifier; + + int modifier = 100; + if (modifier1 >= 0 && modifier2 >= 0) modifier = Math.min(modifier1, modifier2); + else if (modifier1 <= 0 && modifier2 >= 0) modifier = modifier2; + else if (modifier2 <= 0 && modifier1 >= 0) modifier = modifier1; + + if (modifier != 100) { + final int minBaseDamage = player.damagePotential.current - player.weaponDamage.current; + final int maxBaseDamage = player.damagePotential.max - player.weaponDamage.max; + player.damagePotential.add(Math.round(minBaseDamage * ((modifier - 100)/100f)), true); + player.damagePotential.addToMax(Math.round(maxBaseDamage * ((modifier - 100)/100f))); + } + } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MapController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MapController.java index 47ea75a32..1bcb30ae1 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MapController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MapController.java @@ -146,20 +146,20 @@ public final class MapController { for (PredefinedMap m : world.maps.getAllMaps()) { m.resetTemporaryData(); } - controllers.monsterSpawnController.spawnAll(world.model.currentMap, world.model.currentTileMap); + controllers.monsterSpawnController.spawnAll(world.model.currentMaps.map, world.model.currentMaps.tileMap); world.model.worldData.tickWorldTime(20); controllers.gameRoundController.resetRoundTimers(); } public void rest(MapObject area) { lotsOfTimePassed(); - world.model.player.setSpawnPlace(world.model.currentMap.name, area.id); + world.model.player.setSpawnPlace(world.model.currentMaps.map.name, area.id); worldEventListeners.onPlayerRested(); } public boolean canEnterKeyArea(MapObject area) { if (ConversationController.canFulfillRequirement(world, area.enteringRequirement)) { - ConversationController.requirementFulfilled(world, area.enteringRequirement); + ConversationController.requirementFulfilled(world, area.enteringRequirement, controllers); return true; } worldEventListeners.onPlayerSteppedOnKeyArea(area); @@ -168,7 +168,7 @@ public final class MapController { public void resetMapsNotRecentlyVisited() { for (PredefinedMap m : world.maps.getAllMaps()) { - if (m == world.model.currentMap) continue; + if (m == world.model.currentMaps.map) continue; if (m.isRecentlyVisited()) continue; if (m.hasResetTemporaryData()) continue; m.resetTemporaryData(); @@ -176,12 +176,12 @@ public final class MapController { } public void applyCurrentMapReplacements(final Resources res, boolean updateWorldmap) { - if (!applyReplacements(world.model.currentMap, world.model.currentTileMap)) return; + if (!applyReplacements(world.model.currentMaps.map, world.model.currentMaps.tileMap)) return; world.maps.worldMapRequiresUpdate = true; if (!updateWorldmap) return; WorldMapController.updateWorldMap(world, res); - mapLayoutListeners.onMapTilesChanged(world.model.currentMap, world.model.currentTileMap); + mapLayoutListeners.onMapTilesChanged(world.model.currentMaps.map, world.model.currentMaps.tileMap); } private boolean applyReplacements(PredefinedMap map, LayeredTileMap tileMap) { @@ -190,7 +190,7 @@ public final class MapController { for(ReplaceableMapSection replacement : tileMap.replacements) { if (replacement.isApplied) continue; if (!satisfiesCondition(replacement)) continue; - else ConversationController.requirementFulfilled(world, replacement.requirement); + else ConversationController.requirementFulfilled(world, replacement.requirement, controllers); tileMap.applyReplacement(replacement); for (ReplaceableMapSection impactedReplacement : tileMap.replacements) { if (impactedReplacement.isApplied && impactedReplacement.replacementArea.intersects(replacement.replacementArea)) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java index b9e6be9f7..0a352aadd 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MonsterMovementController.java @@ -27,7 +27,7 @@ public final class MonsterMovementController implements EvaluateWalkable { public void moveMonsters() { long currentTime = System.currentTimeMillis(); - for (MonsterSpawnArea a : world.model.currentMap.spawnAreas) { + for (MonsterSpawnArea a : world.model.currentMaps.map.spawnAreas) { for (Monster m : a.monsters) { if (m.nextActionTime <= currentTime) { moveMonster(m, a); @@ -37,7 +37,7 @@ public final class MonsterMovementController implements EvaluateWalkable { } public void attackWithAgressiveMonsters() { - for (MonsterSpawnArea a : world.model.currentMap.spawnAreas) { + for (MonsterSpawnArea a : world.model.currentMaps.map.spawnAreas) { for (Monster m : a.monsters) { if (!m.isAgressive(world.model.player)) continue; if (!m.isAdjacentTo(world.model.player)) continue; @@ -75,8 +75,8 @@ public final class MonsterMovementController implements EvaluateWalkable { } private void moveMonster(final Monster m, final MonsterSpawnArea area) { - PredefinedMap map = world.model.currentMap; - LayeredTileMap tileMap = world.model.currentTileMap; + PredefinedMap map = world.model.currentMaps.map; + LayeredTileMap tileMap = world.model.currentMaps.tileMap; m.nextActionTime = System.currentTimeMillis() + getMillisecondsPerMove(m); if (m.movementDestination != null && m.position.equals(m.movementDestination)) { // Monster has been moving and arrived at the destination. @@ -159,7 +159,7 @@ public final class MonsterMovementController implements EvaluateWalkable { @Override public boolean isWalkable(CoordRect r, Monster m) { - return monsterCanMoveTo(null, world.model.currentMap, world.model.currentTileMap, r, m.area.ignoreAreas); + return monsterCanMoveTo(null, world.model.currentMaps.map, world.model.currentMaps.tileMap, r, m.area.ignoreAreas); } public void moveMonsterToNextPosition(final Monster m, final PredefinedMap map) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java index a7d1e67c6..0646080f2 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MovementController.java @@ -7,6 +7,7 @@ import com.gpl.rpg.AndorsTrail.AndorsTrailPreferences; import com.gpl.rpg.AndorsTrail.context.ControllerContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; import com.gpl.rpg.AndorsTrail.controller.listeners.PlayerMovementListeners; +import com.gpl.rpg.AndorsTrail.model.MapBundle; import com.gpl.rpg.AndorsTrail.model.ModelContainer; import com.gpl.rpg.AndorsTrail.model.actor.Monster; import com.gpl.rpg.AndorsTrail.model.actor.Player; @@ -56,7 +57,7 @@ public final class MovementController implements TimedMessageTask.Callback { protected void onPostExecute(Void result) { super.onPostExecute(result); stopMovement(); - playerMovementListeners.onPlayerEnteredNewMap(world.model.currentMap, world.model.player.position); + playerMovementListeners.onPlayerEnteredNewMap(world.model.currentMaps.map, world.model.player.position); controllers.gameRoundController.resume(); } @@ -83,7 +84,7 @@ public final class MovementController implements TimedMessageTask.Callback { } final ModelContainer model = world.model; - if (model.currentMap != null) model.currentMap.updateLastVisitTime(); + if (model.currentMaps.map != null) model.currentMaps.map.updateLastVisitTime(); 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); @@ -103,19 +104,28 @@ public final class MovementController implements TimedMessageTask.Callback { public void prepareMapAsCurrentMap(PredefinedMap newMap, Resources res, boolean spawnMonsters) { final ModelContainer model = world.model; - model.currentMap = newMap; - cacheCurrentMapData(res, newMap); + MapBundle newMaps = new MapBundle(); + newMaps.map = newMap; + + LayeredTileMap mapTiles = TMXMapTranslator.readLayeredTileMap(res, world.tileManager.tileCache, newMaps.map); + mapTiles.changeColorFilter(newMaps.map.currentColorFilter); + TileCollection cachedTiles = world.tileManager.loadTilesFor(newMaps.map, mapTiles, world, res); + newMaps.tileMap = mapTiles; + newMaps.tiles = cachedTiles; + world.tileManager.cacheAdjacentMaps(res, world, newMaps.map); + world.model.currentMaps = newMaps; + //Apply replacements before spawning, so that MonsterSpawnArea's isActive variable is up to date. controllers.mapController.applyCurrentMapReplacements(res, false); if (spawnMonsters) { if (!newMap.isRecentlyVisited()) { - controllers.monsterSpawnController.spawnAll(newMap, model.currentTileMap); + controllers.monsterSpawnController.spawnAll(newMap, model.currentMaps.tileMap); } } controllers.mapController.prepareScriptsOnCurrentMap(); newMap.visited = true; newMap.updateLastVisitTime(); - moveBlockedActors(newMap, model.currentTileMap); + moveBlockedActors(newMap, model.currentMaps.tileMap); refreshMonsterAggressiveness(newMap, model.player); controllers.effectController.updateSplatters(newMap); WorldMapController.updateWorldMap(world, res); @@ -131,7 +141,7 @@ public final class MovementController implements TimedMessageTask.Callback { if (!findWalkablePosition(dx, dy)) return; - Monster m = world.model.currentMap.getMonsterAt(world.model.player.nextPosition); + Monster m = world.model.currentMaps.map.getMonsterAt(world.model.player.nextPosition); if (m != null) { controllers.mapController.steppedOnMonster(m, world.model.player.nextPosition); return; @@ -196,14 +206,14 @@ public final class MovementController implements TimedMessageTask.Callback { ,player.position.y + dy ); - if (!world.model.currentTileMap.isWalkable(player.nextPosition)) return false; + if (!world.model.currentMaps.tileMap.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 = world.model.currentMap.getMonsterAt(player.nextPosition); + Monster m = world.model.currentMaps.map.getMonsterAt(player.nextPosition); if (m != null && !m.isAgressive(player)) return true; // avoid MOVEMENTAGGRESSIVENESS settings for NPCs if (aggressiveness == AndorsTrailPreferences.MOVEMENTAGGRESSIVENESS_AGGRESSIVE && m == null) return false; @@ -225,7 +235,7 @@ public final class MovementController implements TimedMessageTask.Callback { public void moveToNextIfPossible() { final Player player = world.model.player; - final PredefinedMap currentMap = world.model.currentMap; + final PredefinedMap currentMap = world.model.currentMaps.map; final Coord newPosition = player.nextPosition; for (MapObject o : currentMap.eventObjects) { @@ -251,7 +261,7 @@ public final class MovementController implements TimedMessageTask.Callback { if (!world.model.uiSelections.isInCombat) { //currentMap can be outdated due to mapchange events processed above. - Loot loot = world.model.currentMap.getBagAt(newPosition); + Loot loot = world.model.currentMaps.map.getBagAt(newPosition); if (loot != null) controllers.itemController.playerSteppedOnLootBag(loot); } } @@ -262,7 +272,7 @@ public final class MovementController implements TimedMessageTask.Callback { public void respawnPlayer(Resources res) { placePlayerAt(res, MapObject.MapObjectType.rest, world.model.player.getSpawnMap(), world.model.player.getSpawnPlace(), 0, 0); - playerMovementListeners.onPlayerEnteredNewMap(world.model.currentMap, world.model.player.position); + playerMovementListeners.onPlayerEnteredNewMap(world.model.currentMaps.map, world.model.player.position); } public void respawnPlayerAsync() { placePlayerAsyncAt(MapObject.MapObjectType.rest, world.model.player.getSpawnMap(), world.model.player.getSpawnPlace(), 0, 0); @@ -311,16 +321,6 @@ public final class MovementController implements TimedMessageTask.Callback { return null; } - private void cacheCurrentMapData(final Resources res, final PredefinedMap nextMap) { - LayeredTileMap mapTiles = TMXMapTranslator.readLayeredTileMap(res, world.tileManager.tileCache, nextMap); - mapTiles.changeColorFilter(nextMap.currentColorFilter); - TileCollection cachedTiles = world.tileManager.loadTilesFor(nextMap, mapTiles, world, res); - world.model.currentTileMap = mapTiles; - world.tileManager.currentMapTiles = cachedTiles; - world.tileManager.cacheAdjacentMaps(res, world, nextMap); - } - - private int movementDx; private int movementDy; public void startMovement(int dx, int dy, Coord destination) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/SkillController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/SkillController.java index cd749e999..cb696efa1 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/SkillController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/SkillController.java @@ -307,6 +307,15 @@ public final class SkillController { ItemType mainHandItem = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.weapon); ItemType offHandItem = player.inventory.getItemTypeInWearSlot(Inventory.WearSlot.shield); + final int skillLevelFightStyleUnarmedUnarmored = player.getSkillLevel(SkillID.fightstyleUnarmedUnarmored); + if (skillLevelFightStyleUnarmedUnarmored > 0 && isUnarmored(player) && mainHandItem == null && offHandItem == null) { + player.blockChance += SkillCollection.PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_BC * skillLevelFightStyleUnarmedUnarmored; + player.damageResistance += SkillCollection.PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_DR * skillLevelFightStyleUnarmedUnarmored; + player.attackChance += SkillCollection.PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_AC * skillLevelFightStyleUnarmedUnarmored; + player.damagePotential.addToMax(SkillCollection.PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_DMG_MAX * skillLevelFightStyleUnarmedUnarmored); + player.criticalMultiplier = 1 + ((float)SkillCollection.PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_CM_PERCENT / 100) * skillLevelFightStyleUnarmedUnarmored; + } + if (isWielding2HandItem(mainHandItem, offHandItem)) { int skillLevelFightStyle = player.getSkillLevel(SkillID.fightstyle2hand); int skillLevelSpecialization = player.getSkillLevel(SkillID.specialization2hand); @@ -386,6 +395,11 @@ public final class SkillController { if (itemType.effects_equip == null) return; player.damagePotential.addToMax(getPercentage(itemType.effects_equip.stats.increaseMaxDamage, percentForPositiveValues, percentForNegativeValues)); player.damagePotential.add(getPercentage(itemType.effects_equip.stats.increaseMinDamage, percentForPositiveValues, percentForNegativeValues), false); + + if (itemType.isWeapon()) { + player.weaponDamage.addToMax(getPercentage(itemType.effects_equip.stats.increaseMaxDamage, percentForPositiveValues, percentForNegativeValues)); + player.weaponDamage.add(getPercentage(itemType.effects_equip.stats.increaseMinDamage, percentForPositiveValues, percentForNegativeValues), false); + } } private static void addPercentCriticalSkill(Player player, ItemType itemType, int percentForPositiveValues, int percentForNegativeValues) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/WorldMapController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/WorldMapController.java index 74ef5dcfd..d1e31f6b5 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/WorldMapController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/WorldMapController.java @@ -41,7 +41,7 @@ public final class WorldMapController { public static final int WORLDMAP_DISPLAY_TILESIZE = WORLDMAP_SCREENSHOT_TILESIZE; public static void updateWorldMap(final WorldContext world, final Resources res) { - updateWorldMap(world, world.model.currentMap, world.model.currentTileMap, world.tileManager.currentMapTiles, res); + updateWorldMap(world, world.model.currentMaps.map, world.model.currentMaps.tileMap, world.model.currentMaps.tiles, res); } private static void updateWorldMap( @@ -303,7 +303,7 @@ public final class WorldMapController { } public static boolean displayWorldMap(Context context, WorldContext world) { - String worldMapSegmentName = world.maps.getWorldMapSegmentNameForMap(world.model.currentMap.name); + String worldMapSegmentName = world.maps.getWorldMapSegmentNameForMap(world.model.currentMaps.map.name); if (worldMapSegmentName == null) { Toast.makeText(context, context.getResources().getString(R.string.display_worldmap_not_available), Toast.LENGTH_LONG).show(); return false; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/MapBundle.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/MapBundle.java new file mode 100644 index 000000000..fa102330f --- /dev/null +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/MapBundle.java @@ -0,0 +1,11 @@ +package com.gpl.rpg.AndorsTrail.model; + +import com.gpl.rpg.AndorsTrail.model.map.LayeredTileMap; +import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; +import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection; + +public final class MapBundle { + public PredefinedMap map; + public LayeredTileMap tileMap; + public TileCollection tiles; +} diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ModelContainer.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ModelContainer.java index 4a768bf80..e4d942d28 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ModelContainer.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ModelContainer.java @@ -9,6 +9,7 @@ import com.gpl.rpg.AndorsTrail.context.WorldContext; import com.gpl.rpg.AndorsTrail.model.actor.Player; import com.gpl.rpg.AndorsTrail.model.map.LayeredTileMap; import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap; +import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection; public final class ModelContainer { @@ -17,8 +18,7 @@ public final class ModelContainer { public final CombatLog combatLog = new CombatLog(); public final GameStatistics statistics; public final WorldData worldData; - public PredefinedMap currentMap; - public LayeredTileMap currentTileMap; + public MapBundle currentMaps = new MapBundle();; public ModelContainer(int startLives, boolean unlimitedSaves) { player = new Player(); @@ -31,13 +31,13 @@ public final class ModelContainer { public ModelContainer(DataInputStream src, WorldContext world, ControllerContext controllers, int fileversion) throws IOException { this.player = Player.newFromParcel(src, world, controllers, fileversion); - this.currentMap = world.maps.findPredefinedMap(src.readUTF()); + this.currentMaps.map = world.maps.findPredefinedMap(src.readUTF()); this.uiSelections = new InterfaceData(src, fileversion); if (uiSelections.selectedPosition != null) { - this.uiSelections.selectedMonster = currentMap.getMonsterAt(uiSelections.selectedPosition); + this.uiSelections.selectedMonster = currentMaps.map.getMonsterAt(uiSelections.selectedPosition); } this.statistics = new GameStatistics(src, world, fileversion); - this.currentTileMap = null; + this.currentMaps.tileMap = null; if (fileversion >= 40) { this.worldData = new WorldData(src, fileversion); } else { @@ -47,7 +47,7 @@ public final class ModelContainer { public void writeToParcel(DataOutputStream dest) throws IOException { player.writeToParcel(dest); - dest.writeUTF(currentMap.name); + dest.writeUTF(currentMaps.map.name); uiSelections.writeToParcel(dest); statistics.writeToParcel(dest); worldData.writeToParcel(dest); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/SkillCollection.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/SkillCollection.java index faa23dbdc..b8d753a58 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/SkillCollection.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/ability/SkillCollection.java @@ -55,6 +55,7 @@ public final class SkillCollection { ,specialization2hand ,specializationWeaponShield ,weaponProficiencyPole + ,fightstyleUnarmedUnarmored } // should be in the same number &U order as in arrays.xml @@ -117,6 +118,11 @@ public final class SkillCollection { public static final int PER_SKILLPOINT_INCREASE_SPECIALIZATION_2HAND_AC_PERCENT = 20; public static final int PER_SKILLPOINT_INCREASE_FIGHTSTYLE_WEAPON_AC_PERCENT = 25; public static final int PER_SKILLPOINT_INCREASE_FIGHTSTYLE_SHIELD_BC_PERCENT = 25; + public static final int PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_BC = 5; + public static final int PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_DR = 1; + public static final int PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_AC = 12; + public static final int PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_DMG_MAX = 4; + public static final int PER_SKILLPOINT_INCREASE_UNARMED_UNARMORED_CM_PERCENT = 25; public static final int PER_SKILLPOINT_INCREASE_SPECIALIZATION_WEAPON_AC_PERCENT = 50; public static final int PER_SKILLPOINT_INCREASE_SPECIALIZATION_WEAPON_DMG_PERCENT = 20; public static final int DUALWIELD_EFFICIENCY_LEVEL2 = 100; @@ -223,6 +229,9 @@ public final class SkillCollection { initializeSkill(new SkillInfo(SkillID.fightstyleWeaponShield, 2, SkillInfo.LevelUpType.alwaysShown, SkillCategory.specialty, new SkillLevelRequirement[] { SkillLevelRequirement.requireExperienceLevels(15, 0) }, position++)); + initializeSkill(new SkillInfo(SkillID.fightstyleUnarmedUnarmored, 3, SkillInfo.LevelUpType.alwaysShown, SkillCategory.specialty, new SkillLevelRequirement[] { + SkillLevelRequirement.requireExperienceLevels(15, 0) + }, position++)); initializeSkill(new SkillInfo(SkillID.specializationDualWield, 1, SkillInfo.LevelUpType.alwaysShown, SkillCategory.specialty, new SkillLevelRequirement[] { SkillLevelRequirement.requireExperienceLevels(45, 0) ,SkillLevelRequirement.requireOtherSkill(SkillID.fightstyleDualWield, 2) 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 845adfafa..7d7fdedd6 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 @@ -12,6 +12,7 @@ public final class AbilityModifierTraits { public final int increaseBlockChance; public final int increaseMinDamage; public final int increaseMaxDamage; + public final int setNonWeaponDamageModifier; public final int increaseCriticalSkill; public final float setCriticalMultiplier; public final int increaseDamageResistance; @@ -27,6 +28,7 @@ public final class AbilityModifierTraits { , int increaseBlockChance , int increaseMinDamage , int increaseMaxDamage + , int setNonWeaponDamageModifier , int increaseCriticalSkill , float setCriticalMultiplier , int increaseDamageResistance @@ -41,6 +43,7 @@ public final class AbilityModifierTraits { this.increaseBlockChance = increaseBlockChance; this.increaseMinDamage = increaseMinDamage; this.increaseMaxDamage = increaseMaxDamage; + this.setNonWeaponDamageModifier = setNonWeaponDamageModifier; this.increaseCriticalSkill = increaseCriticalSkill; this.setCriticalMultiplier = setCriticalMultiplier; this.increaseDamageResistance = increaseDamageResistance; 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 c7224ce39..603977973 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java @@ -3,8 +3,12 @@ package com.gpl.rpg.AndorsTrail.model.actor; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.Map.Entry; import java.util.UUID; @@ -19,6 +23,7 @@ import com.gpl.rpg.AndorsTrail.model.ability.SkillCollection; import com.gpl.rpg.AndorsTrail.model.item.DropListCollection; import com.gpl.rpg.AndorsTrail.model.item.Inventory; import com.gpl.rpg.AndorsTrail.model.item.Loot; +import com.gpl.rpg.AndorsTrail.model.quest.Quest; import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress; import com.gpl.rpg.AndorsTrail.savegames.LegacySavegameFormatReaderForPlayer; import com.gpl.rpg.AndorsTrail.util.Coord; @@ -40,8 +45,9 @@ public final class Player extends Actor { public int useItemCost; public int reequipCost; public int totalExperience; + public final Range weaponDamage = new Range(); - private final HashMap > questProgress = new HashMap >(); + private final LinkedHashMap > questProgress = new LinkedHashMap >(); private String spawnMap; private String spawnPlace; private final HashMap alignments = new HashMap(); @@ -117,6 +123,7 @@ public final class Player extends Actor { this.ap.set(baseTraits.maxAP, baseTraits.maxAP); this.health.set(baseTraits.maxHP, baseTraits.maxHP); this.conditions.clear(); + this.weaponDamage.set(0, 0); Loot startItems = new Loot(); dropLists.getDropList(DropListCollection.DROPLIST_STARTITEMS).createRandomLoot(startItems, this); @@ -139,6 +146,9 @@ public final class Player extends Actor { public boolean hasAnyQuestProgress(String questID) { return questProgress.containsKey(questID); } + public Collection getAllQuestProgressIDs() { + return new ArrayList(this.questProgress.keySet()); + } public boolean isLatestQuestProgress(String questID, int progress) { if (!questProgress.containsKey(questID)) return false; if (!questProgress.get(questID).contains(progress)) return false; @@ -343,16 +353,30 @@ public final class Player extends Actor { this.spawnPlace = src.readUTF(); if (fileversion > 13) { + LinkedHashMap > questProgress = new LinkedHashMap >(); final int numQuests = src.readInt(); for(int i = 0; i < numQuests; ++i) { final String questID = src.readUTF(); - this.questProgress.put(questID, new HashSet()); + questProgress.put(questID, new HashSet()); final int numProgress = src.readInt(); for(int j = 0; j < numProgress; ++j) { int progress = src.readInt(); - this.questProgress.get(questID).add(progress); + questProgress.get(questID).add(progress); } } + + // questprogress is randomly sorted until 52 so sort it by quest order + if (fileversion < 52) { + for (Quest q : world.quests.getAllQuests()) { + final HashSet questSteps = questProgress.get(q.questID); + if (questSteps != null) { + this.questProgress.put(q.questID, questSteps); + } + } + } else { + this.questProgress.putAll(questProgress); + } + } this.availableSkillIncreases = 0; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/item/Inventory.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/item/Inventory.java index 535156460..43d719456 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/item/Inventory.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/item/Inventory.java @@ -56,16 +56,7 @@ public final class Inventory extends ItemContainer { wear[slot.ordinal()] = type; } - public boolean isWearing(String itemTypeID) { - for(int i = 0; i < NUM_WORN_SLOTS; ++i) { - if (wear[i] == null) continue; - if (wear[i].id.equals(itemTypeID)) return true; - } - return false; - } - public boolean isWearing(String itemTypeID, int minNumber) { - if (minNumber == 0) return isWearing(itemTypeID); for(int i = 0; i < NUM_WORN_SLOTS; ++i) { if (wear[i] == null) continue; if (wear[i].id.equals(itemTypeID)) minNumber--; 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 b13269174..20b383bd2 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/PredefinedMap.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/PredefinedMap.java @@ -64,6 +64,16 @@ public final class PredefinedMap { assert(size.height > 0); this.isOutdoors = isOutdoors; this.initialColorFilter = colorFilter; + + if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { + for (int i = 0; i < spawnAreas.length; i++) { + for (int j = i + 1; j < spawnAreas.length; j++) { + if (spawnAreas[i].areaID.equals(spawnAreas[j].areaID)) { + L.log("WARNING: duplicate areaID " + spawnAreas[i].areaID + " in map " + this.name); + } + } + } + } } public final boolean isOutside(final Coord p) { return isOutside(p.x, p.y); } @@ -351,7 +361,7 @@ public final class PredefinedMap { public boolean shouldSaveMapData(WorldContext world) { if (!hasResetTemporaryData()) return true; - if (this == world.model.currentMap) return true; + if (this == world.model.currentMaps.map) return true; if (!groundBags.isEmpty()) return true; for (MonsterSpawnArea a : spawnAreas) { if (this.visited && a.isUnique) return true; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/script/Requirement.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/script/Requirement.java index 450994a0a..1e7c149a6 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/script/Requirement.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/script/Requirement.java @@ -20,6 +20,7 @@ public final class Requirement { ,factionScore ,random ,factionScoreEquals + ,wearRemove } public final RequirementType requireType; @@ -68,6 +69,8 @@ public final class Requirement { return requireID != null; case inventoryKeep: case inventoryRemove: + case wear: + case wearRemove: case usedItem: return requireID != null && value >= 0; case killedMonster: @@ -83,10 +86,8 @@ public final class Requirement { return chance != null; case timerElapsed: return requireID != null && value >= 0; - case wear: case factionScore: case factionScoreEquals: - return requireID != null; default: return false; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java index e70ec0048..7ff7ca78b 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/ResourceLoader.java @@ -325,7 +325,7 @@ public final class ResourceLoader { loader.prepareTileset(R.drawable.monsters_man1, "monsters_man1", sz1x1, sz1x1, mTileSize); loader.prepareTileset(R.drawable.monsters_men, "monsters_men", new Size(9, 1), sz1x1, mTileSize); loader.prepareTileset(R.drawable.monsters_men2, "monsters_men2", new Size(10, 1), sz1x1, mTileSize); - loader.prepareTileset(R.drawable.monsters_misc, "monsters_misc", new Size(12, 1), sz1x1, mTileSize); + loader.prepareTileset(R.drawable.monsters_misc, "monsters_misc", new Size(13, 1), sz1x1, mTileSize); loader.prepareTileset(R.drawable.monsters_rats, "monsters_rats", new Size(5, 1), sz1x1, mTileSize); loader.prepareTileset(R.drawable.monsters_redshrike1, "monsters_redshrike1", sz7x1, sz1x1, mTileSize); loader.prepareTileset(R.drawable.monsters_rltiles1, "monsters_rltiles1", new Size(20, 8), sz1x1, mTileSize); @@ -356,6 +356,7 @@ public final class ResourceLoader { loader.prepareTileset(R.drawable.monsters_unknown, "monsters_unknown", sz1x1, sz1x1, mTileSize); loader.prepareTileset(R.drawable.monsters_arulirs, "monsters_arulirs", new Size(8, 2), sz1x1, mTileSize); loader.prepareTileset(R.drawable.monsters_fatboy73, "monsters_fatboy73", new Size(20, 12), sz1x1, mTileSize); + loader.prepareTileset(R.drawable.monsters_giantbasilisk, "monsters_giantbasilisk", sz1x1, sz2x2, mTileSize); /*INSERT_NPCS_TILESETS_HERE*/ loader.prepareTileset(R.drawable.map_bed_1, "map_bed_1", mapTileSize, sz1x1, mTileSize); @@ -404,6 +405,7 @@ public final class ResourceLoader { loader.prepareTileset(R.drawable.map_shop_1, "map_shop_1", mapTileSize, sz1x1, mTileSize); loader.prepareTileset(R.drawable.map_sign_ladder_1, "map_sign_ladder_1", mapTileSize, sz1x1, mTileSize); loader.prepareTileset(R.drawable.map_table_1, "map_table_1", mapTileSize, sz1x1, mTileSize); + loader.prepareTileset(R.drawable.map_table_2, "map_table_2", new Size(14, 8), sz1x1, mTileSize); loader.prepareTileset(R.drawable.map_trail_1, "map_trail_1", mapTileSize, sz1x1, mTileSize); loader.prepareTileset(R.drawable.map_transition_1, "map_transition_1", mapTileSize, sz1x1, mTileSize); loader.prepareTileset(R.drawable.map_transition_2, "map_transition_2", mapTileSize, sz1x1, mTileSize); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ResourceParserUtils.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ResourceParserUtils.java index 8456c7578..3619b43ff 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ResourceParserUtils.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ResourceParserUtils.java @@ -125,6 +125,7 @@ public final class ResourceParserUtils { ,o.optInt(JsonFieldNames.AbilityModifierTraits.increaseBlockChance, 0) ,increaseAttackDamage != null ? increaseAttackDamage.current : 0 ,increaseAttackDamage != null ? increaseAttackDamage.max : 0 + , o.optInt(JsonFieldNames.AbilityModifierTraits.setNonWeaponDamageModifier, 100) ,o.optInt(JsonFieldNames.AbilityModifierTraits.increaseCriticalSkill, 0) ,(float)o.optDouble(JsonFieldNames.AbilityModifierTraits.setCriticalMultiplier, 0) ,o.optInt(JsonFieldNames.AbilityModifierTraits.increaseDamageResistance, 0) diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/json/JsonFieldNames.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/json/JsonFieldNames.java index 97e983a7e..7f784b84a 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/json/JsonFieldNames.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/json/JsonFieldNames.java @@ -30,6 +30,7 @@ public final class JsonFieldNames { public static final String increaseCriticalSkill = "increaseCriticalSkill"; public static final String setCriticalMultiplier = "setCriticalMultiplier"; public static final String increaseAttackDamage = "increaseAttackDamage"; + public static final String setNonWeaponDamageModifier = "setNonWeaponDamageModifier"; public static final String increaseBlockChance = "increaseBlockChance"; public static final String increaseDamageResistance = "increaseDamageResistance"; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileManager.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileManager.java index 9ff2bf9d0..b56026ec0 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileManager.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/tiles/TileManager.java @@ -98,7 +98,6 @@ public final class TileManager { public final TileCache tileCache = new TileCache(); public TileCollection preloadedTiles;// = new TileCollection(116); - public TileCollection currentMapTiles; public TileCollection adjacentMapTiles; private final HashSet preloadedTileIDs = new HashSet(); @@ -177,9 +176,9 @@ public final class TileManager { - public void setImageViewTile(Resources res, TextView textView, Monster monster) { setImageViewTileForMonster(res, textView, monster.iconID); } + public void setImageViewTile(Resources res, TextView textView, Monster monster, TileCollection tiles) { setImageViewTileForMonster(res, textView, monster.iconID, tiles); } public void setImageViewTile(Resources res, TextView textView, Player player) { setImageViewTileForPlayer(res, textView, player.iconID); } - public void setImageViewTileForMonster(Resources res, TextView textView, int iconID) { setImageViewTile(res, textView, currentMapTiles.getBitmap(iconID)); } + public void setImageViewTileForMonster(Resources res, TextView textView, int iconID, TileCollection tiles) { setImageViewTile(res, textView, tiles.getBitmap(iconID)); } public void setImageViewTileForPlayer(Resources res, TextView textView, int iconID) { setImageViewTile(res, textView, preloadedTiles.getBitmap(iconID)); } public void setImageViewTile(Resources res, TextView textView, ActorConditionType conditionType) { setImageViewTile(res, textView, preloadedTiles.getBitmap(conditionType.iconID)); } public void setImageViewTile(Resources res, TextView textView, ActorConditionType conditionType, boolean immunityOverlay) { setImageViewTile(res, textView, preloadedTiles.getBitmap(conditionType.iconID), immunityOverlay); } @@ -249,9 +248,9 @@ public final class TileManager { } } - public void setImageViewTile(Resources res, ImageView imageView, Monster monster) { setImageViewTileForMonster(res, imageView, monster.iconID); } + public void setImageViewTile(Resources res, ImageView imageView, Monster monster, TileCollection tiles) { setImageViewTileForMonster(res, imageView, monster.iconID, tiles); } public void setImageViewTile(Resources res, ImageView imageView, Player player) { setImageViewTileForPlayer(res, imageView, player.iconID); } - public void setImageViewTileForMonster(Resources res, ImageView imageView, int iconID) { setImageViewTile(res, imageView, currentMapTiles.getBitmap(iconID)); } + public void setImageViewTileForMonster(Resources res, ImageView imageView, int iconID, TileCollection tiles) { setImageViewTile(res, imageView, tiles.getBitmap(iconID)); } public void setImageViewTileForPlayer(Resources res, ImageView imageView, int iconID) { setImageViewTile(res, imageView, preloadedTiles.getBitmap(iconID)); } // public void setImageViewTile(Resources res, ImageView imageView, ActorConditionType conditionType) { setImageViewTile(res, imageView, preloadedTiles.getBitmap(conditionType.iconID)); } public void setImageViewTile(Context ctx, ImageView imageView, ActorConditionType conditionType, boolean immunityOverlay) { setImageViewTile(ctx, imageView, preloadedTiles.getBitmap(conditionType.iconID), immunityOverlay); } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegamesContentAdaptations.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegamesContentAdaptations.java index dd413f982..60d403a4f 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegamesContentAdaptations.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/LegacySavegamesContentAdaptations.java @@ -29,7 +29,7 @@ public class LegacySavegamesContentAdaptations { for (MonsterSpawnArea newarea : fields5Map.spawnAreas) { if (newarea.areaID.equals("guynmart_robber1")) { controllers.monsterSpawnController.spawnAllInArea(fields5Map, - (world.model.currentMap == fields5Map ? world.model.currentTileMap : null), + (world.model.currentMaps.map == fields5Map ? world.model.currentMaps.tileMap : null), newarea, true); break; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/Savegames.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/Savegames.java index 7a3aead4f..928b49f9a 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/Savegames.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/savegames/Savegames.java @@ -233,7 +233,7 @@ public final class Savegames { private static void onWorldLoaded(Resources res, WorldContext world, ControllerContext controllers) { controllers.actorStatsController.recalculatePlayerStats(world.model.player); controllers.mapController.resetMapsNotRecentlyVisited(); - controllers.movementController.prepareMapAsCurrentMap(world.model.currentMap, res, false); + controllers.movementController.prepareMapAsCurrentMap(world.model.currentMaps.map, res, false); controllers.gameRoundController.resetRoundTimers(); } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/ListOfListeners.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/ListOfListeners.java index 6a8e5b808..c07f586a5 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/ListOfListeners.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/util/ListOfListeners.java @@ -8,7 +8,7 @@ import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; public class ListOfListeners { private final ArrayList> listeners = new ArrayList>(); - public final void add(T listener) { + public synchronized 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 final void remove(T listenerToRemove) { + public synchronized 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) { @@ -26,32 +26,32 @@ public class ListOfListeners { } } } - public final void clear() { + public synchronized final void clear() { listeners.clear(); } - protected final void callAllListeners(Function e) { + protected synchronized 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 final void callAllListeners(Function1 e, Arg1 arg) { + protected synchronized 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 final void callAllListeners(Function2 e, Arg1 arg1, Arg2 arg2) { + protected synchronized 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) { + protected synchronized 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); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/AbilityModifierInfoView.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/AbilityModifierInfoView.java index 6d1daf839..019f46e91 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/AbilityModifierInfoView.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/AbilityModifierInfoView.java @@ -19,6 +19,7 @@ public final class AbilityModifierInfoView extends LinearLayout { private final TextView abilitymodifierinfo_change_attack_cost; private final TextView abilitymodifierinfo_change_attack_chance; private final TextView abilitymodifierinfo_change_attack_damage; + private final TextView abilitymodifierinfo_set_damage_modifier; private final TextView abilitymodifierinfo_change_critical_skill; private final TextView abilitymodifierinfo_change_critical_multiplier; private final TextView abilitymodifierinfo_change_block_chance; @@ -38,6 +39,7 @@ public final class AbilityModifierInfoView extends LinearLayout { abilitymodifierinfo_change_attack_cost = (TextView) findViewById(R.id.abilitymodifierinfo_change_attack_cost); abilitymodifierinfo_change_attack_chance = (TextView) findViewById(R.id.abilitymodifierinfo_change_attack_chance); abilitymodifierinfo_change_attack_damage = (TextView) findViewById(R.id.abilitymodifierinfo_change_attack_damage); + abilitymodifierinfo_set_damage_modifier = (TextView) findViewById(R.id.abilitymodifierinfo_set_damage_modifier); abilitymodifierinfo_change_critical_skill = (TextView) findViewById(R.id.abilitymodifierinfo_change_critical_skill); abilitymodifierinfo_change_critical_multiplier = (TextView) findViewById(R.id.abilitymodifierinfo_change_critical_multiplier); abilitymodifierinfo_change_block_chance = (TextView) findViewById(R.id.abilitymodifierinfo_change_block_chance); @@ -89,6 +91,12 @@ public final class AbilityModifierInfoView extends LinearLayout { } abilitymodifierinfo_change_attack_damage.setVisibility(View.VISIBLE); } + + if (isWeapon) { + final int nonWeaponDamageModifier = traits.setNonWeaponDamageModifier > 0 ? traits.setNonWeaponDamageModifier : 100; + abilitymodifierinfo_set_damage_modifier.setText(res.getString(R.string.iteminfo_effect_set_damage_modifier, nonWeaponDamageModifier)); + abilitymodifierinfo_set_damage_modifier.setVisibility(View.VISIBLE); + } } private void displayIfNonZero(int statChange, TextView textView, int stringresource_increase, int stringresource_decrease) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/CombatView.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/CombatView.java index 105589936..2088625cb 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/CombatView.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/CombatView.java @@ -197,7 +197,7 @@ public final class CombatView extends RelativeLayout implements CombatSelectionL currentMonster = null; if (selectedMonster != null) { monsterBar.setVisibility(View.VISIBLE); - world.tileManager.setImageViewTile(res, monsterInfo, selectedMonster); + world.tileManager.setImageViewTile(res, monsterInfo, selectedMonster, world.model.currentMaps.tiles); updateMonsterHealth(selectedMonster); currentMonster = selectedMonster; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java index d1f2684b4..b7e52ee4e 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/MainView.java @@ -167,8 +167,8 @@ public final class MainView extends SurfaceView sh.setFixedSize(surfaceSize.width, surfaceSize.height); } - if (model.currentMap != null) { - onPlayerEnteredNewMap(model.currentMap, model.player.position); + if (model.currentMaps.map != null) { + onPlayerEnteredNewMap(model.currentMaps.map, model.player.position); } else { redrawAll(RedrawAllDebugReason.SurfaceChanged); } @@ -506,8 +506,8 @@ public final class MainView extends SurfaceView movingSpritesRedrawTick.start(); synchronized (holder) { currentMap = map; - currentTileMap = model.currentTileMap; - tiles = world.tileManager.currentMapTiles; + currentTileMap = model.currentMaps.tileMap; + tiles = world.model.currentMaps.tiles; movingSprites = 0; Size visibleNumberOfTiles = new Size( Math.min(screenSizeTileCount.width, currentMap.size.width) diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/SkillListAdapter.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/SkillListAdapter.java index ec4c2972c..4138a4d2c 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/SkillListAdapter.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/view/SkillListAdapter.java @@ -155,6 +155,7 @@ public final class SkillListAdapter extends ArrayAdapter { case fightstyleDualWield: return R.string.skill_shortdescription_fightstyle_dualwield; case fightstyle2hand: return R.string.skill_shortdescription_fightstyle_2hand; case fightstyleWeaponShield: return R.string.skill_shortdescription_fightstyle_weapon_shield; + case fightstyleUnarmedUnarmored: return R.string.skill_shortdescription_fightstyle_unarmed_unarmored; case specializationDualWield: return R.string.skill_shortdescription_specialization_dualwield; case specialization2hand: return R.string.skill_shortdescription_specialization_2hand; case specializationWeaponShield: return R.string.skill_shortdescription_specialization_weapon_shield;