From c288fce12fe8e92f55534caf5efa395dae937a4a Mon Sep 17 00:00:00 2001 From: Steve Date: Mon, 28 Mar 2016 18:26:02 +0100 Subject: [PATCH 01/26] Windows build fixes. --- src/plat/win32/win32Init.h | 1 + src/system/i18n.c | 4 ++-- src/system/i18n.h | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plat/win32/win32Init.h b/src/plat/win32/win32Init.h index 8e12bef..565d1b6 100644 --- a/src/plat/win32/win32Init.h +++ b/src/plat/win32/win32Init.h @@ -25,3 +25,4 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../../common.h" extern App app; +extern Dev dev; diff --git a/src/system/i18n.c b/src/system/i18n.c index 7283929..5328afa 100644 --- a/src/system/i18n.c +++ b/src/system/i18n.c @@ -54,9 +54,9 @@ void setLanguage(char *applicationName, char *languageCode) if (c[0] != '\0') { - strncat(language, "_", MAX_MESSAGE_LENGTH - strlen(language) - 1); + strncat(language, "_", MAX_DESCRIPTION_LENGTH - strlen(language) - 1); - strncat(language, c, MAX_MESSAGE_LENGTH - strlen(language) - 1); + strncat(language, c, MAX_DESCRIPTION_LENGTH - strlen(language) - 1); } } #else diff --git a/src/system/i18n.h b/src/system/i18n.h index a3263e1..d73d04f 100644 --- a/src/system/i18n.h +++ b/src/system/i18n.h @@ -19,6 +19,10 @@ Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. #include "../common.h" +#ifdef _WIN32 + #include +#endif + #define TABLE_SIZE 255 char *getTranslatedString(char *); From c98acc9ef6651cf6803c6311d638660e81540d3d Mon Sep 17 00:00:00 2001 From: Steve Date: Mon, 28 Mar 2016 18:26:20 +0100 Subject: [PATCH 02/26] Misc. info updates. --- CHANGELOG | 2 ++ README_DEV.md | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 82b2b75..c7c55d2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,8 @@ Changelog 0.6 + * New Campaign missions + * Added new fighters: Razor and Shale, part of the unstable Nation of Tzac * Added control remapping * New game mode: Challenges * Added i18n support diff --git a/README_DEV.md b/README_DEV.md index 14dc63f..d0b16fc 100644 --- a/README_DEV.md +++ b/README_DEV.md @@ -1,10 +1,10 @@ # DEVELOPMENT / DEBUG Stuff -You can run the game with +You can run the game with: `./tbftss -debug` -to access some (rather crude) debugging and development stuff, activated by pressing certain keys on the keyboard. Press the following keys to toggle the states (see the console for output). Note to porters - you shouldn't distribute the game in this state (either as a hard compile or run script), as it could result in unexpected behaviour. +to access some (rather crude) debugging and development stuff, activated by pressing certain keys on the keyboard. Press the following keys to toggle the states (see the console for output). Note to packagers - you shouldn't distribute the game in this state (either as a hard compile or run script), as it could result in unexpected behaviour. * [1] - Make the player immortal * [2] - Unlimited missiles @@ -15,3 +15,9 @@ to access some (rather crude) debugging and development stuff, activated by pres * [9] - Show the current frames per second * [0] - Take a screenshot once per second, saving to /tmp/tbftss on Linux. + +By default, the game will output WARN level messages, or greater. To see INFO level messages, you can use: + +`./tbftss -info` + +Note that using `-debug` will automatically output DEBUG level messages. From 11ce19e6777079899b4eb0a98c8304be4674ac54 Mon Sep 17 00:00:00 2001 From: Steve Date: Mon, 28 Mar 2016 22:33:15 +0100 Subject: [PATCH 03/26] Added Blizzard. --- CHANGELOG | 2 +- data/fighters/blizzard.json | 33 +++++++++++++++++++++++++++++++++ gfx/fighters/blizzard.png | Bin 0 -> 1545 bytes 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 data/fighters/blizzard.json create mode 100644 gfx/fighters/blizzard.png diff --git a/CHANGELOG b/CHANGELOG index c7c55d2..8eb6e73 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,7 +3,7 @@ Changelog 0.6 * New Campaign missions - * Added new fighters: Razor and Shale, part of the unstable Nation of Tzac + * Added new fighters: Bliizard, Razor, and Shale, part of the unstable Nation of Tzac * Added control remapping * New game mode: Challenges * Added i18n support diff --git a/data/fighters/blizzard.json b/data/fighters/blizzard.json new file mode 100644 index 0000000..3d7d2a6 --- /dev/null +++ b/data/fighters/blizzard.json @@ -0,0 +1,33 @@ +{ + "name" : "Blizzard", + "health" : 120, + "shield" : 70, + "speed" : 1.85, + "reloadTime" : 14, + "shieldRechargeRate" : 45, + "texture" : "gfx/fighters/blizzard.png", + "guns" : [ + { + "type" : "BT_PLASMA", + "x" : -14, + "y" : 0 + }, + { + "type" : "BT_PLASMA", + "x" : -14, + "y" : 0 + }, + { + "type" : "BT_PARTICLE", + "x" : 8, + "y" : 0 + }, + { + "type" : "BT_PARTICLE", + "x" : 8, + "y" : 0 + } + ], + "missiles" : 5, + "flags" : "EF_TAKES_DAMAGE" +} diff --git a/gfx/fighters/blizzard.png b/gfx/fighters/blizzard.png new file mode 100644 index 0000000000000000000000000000000000000000..16dfe28785ab652400bc149c4f9992597e3f1621 GIT binary patch literal 1545 zcmV+k2KM=hP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00nVLL_t(Y$F-N+Yh2eA#(#UC zea_r8ql9lDD27r)N$S+bb`zY|b`wjD#?4qW);V*|*?aZjj7A!DJdPeZAclQe-?#Q!-&(Vz z*xg5Z?5QtnY<5Y8+GjGW6y#s&u59(L$woZ%sE-=)c5AwOGBc6q{P#l4ME?IuCID_D z3*F}TL-N?0%sW!p3Ap{QJA_~HLAUjwRkrT!)c;_3M+#`Sz9Y$R&2d)F^!9APW9aB4 zd%g~pr^nC(z4LZf&cIu9U3+dl1+!S}^5(3ZdDzRuEEeU$1?1j6$kzSpZX2FR%b~rAT<75Y%OS5m^;#d@gE3$&IM=_NUw!H| z&c7UX2)&6M8l}4Y(c?j1MYURxByjicBb2v^v+0mh==i<50H{(s*;e|BfBF2^xPBeJ z|K~&fMc>BR#Esvpiv}2aWd`LbmftP+B~yXoXT`tr-9J9f8b9G_q=08#I^Ba=|oEdD5G)fDO0EC@n;H1qxb9NfrUgcgFYmZt$Vym z8Y%uvfvMB;xb+le^p4)>U~ta}BS)vQg9E|N_JbY^P!)rX9I9f_V?FM)?M9AH;TLk? zb~IwK4qf&L{2cq{=8(`qPNAkf^ueGj>9Uc%MmB7hnDoH_HSIx8A)#aH@%q01g( z-4>ZkEn;8MFqR)75tDzEwCgS(UpWu8C%?d(!5MpfEM8uqd8hm4+@Ww!bRqo-!E z?}zB&Hd)2sYB7=s-&{UH*b2G+>r1G-rvCb!48uHAQUJQ*V`~Y2`tTxQy20R~ad2Q) zTN#+2)zsl5$N0v9XF2fILtXoJwFM6HPn7Y4fZtvD19mMzS2AbJGbLr*{Y-gwB|@5x zJHNb!?*|N4$7p<91EoklO0a7&0M~AO$WnEYyPw_8?ArV0u{?+{erO+;|Na5D-oA?5 zw^$ox`n#W^-PO!WpB|;ZG^7Dg)H|j{kqK6G`!{Ywd+EU;`4qfzc zU!2$j@4zePx;ZtVQgyAgP%~D+e5JM7;!V=-fGAX*Pp~Q9unQa%;fM#^PF2+1u>78`4iB zR4MBUu3?b}7Bij4HB!uEp6FNq$-=c%?2HWdb_-c^s7uo3M3#z^(VK2K~|NHb`p0S1SNQ)nI00000NkvXXu0mjfrC$fC literal 0 HcmV?d00001 From ce8f1fed937d965eb91a40f6546d52c85683ea22 Mon Sep 17 00:00:00 2001 From: Steve Date: Tue, 29 Mar 2016 07:09:10 +0100 Subject: [PATCH 04/26] Replaced Rebel Firefly and Nymph with Razor and Shale. --- data/missions/granada/03 - suspect packages #3.json | 4 ++-- data/missions/rothan/02 - rothan defence #2.json | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/data/missions/granada/03 - suspect packages #3.json b/data/missions/granada/03 - suspect packages #3.json index ef8e8e5..893d39f 100644 --- a/data/missions/granada/03 - suspect packages #3.json +++ b/data/missions/granada/03 - suspect packages #3.json @@ -98,7 +98,7 @@ { "name" : "Tzac Commander", "groupName" : "skirmishGroup", - "types" : "Firefly", + "types" : "Razor", "side" : "SIDE_REBEL", "x" : 15, "y" : 40, @@ -107,7 +107,7 @@ }, { "groupName" : "skirmishGroup", - "types" : "Firefly;Nymph", + "types" : "Razor;Shale", "side" : "SIDE_REBEL", "number" : 8, "x" : 15, diff --git a/data/missions/rothan/02 - rothan defence #2.json b/data/missions/rothan/02 - rothan defence #2.json index 36120a7..a9fc104 100644 --- a/data/missions/rothan/02 - rothan defence #2.json +++ b/data/missions/rothan/02 - rothan defence #2.json @@ -59,7 +59,7 @@ { "name" : "Rebel", "groupName" : "Rebels", - "types" : "Nymph;Firefly", + "types" : "Razor;Shale", "side" : "SIDE_REBEL", "x" : -1, "y" : -1, @@ -70,7 +70,7 @@ { "name" : "Rebel", "groupName" : "Rebels", - "types" : "Nymph;Firefly", + "types" : "Razor;Shale", "side" : "SIDE_REBEL", "x" : 15, "y" : -1, @@ -81,7 +81,7 @@ { "name" : "Rebel", "groupName" : "Rebels", - "types" : "Nymph;Firefly", + "types" : "Razor;Shale", "side" : "SIDE_REBEL", "x" : -1, "y" : 15, From e6ea4bff06a75608361e0e7a6e0d95a0efc1d51f Mon Sep 17 00:00:00 2001 From: Steve Date: Tue, 29 Mar 2016 07:09:26 +0100 Subject: [PATCH 05/26] Reworked canAttack logic. --- src/battle/ai.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/battle/ai.c b/src/battle/ai.c index 145b48a..11d5e55 100644 --- a/src/battle/ai.c +++ b/src/battle/ai.c @@ -50,6 +50,7 @@ static void doGunAI(void); static void moveToLeader(void); static void wander(void); static void doWander(void); +static int selectWeaponForTarget(Entity *e); void doAI(void) { @@ -302,7 +303,7 @@ static void findTarget(void) for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) { - if (e->active && (e->flags & EF_TAKES_DAMAGE) && (!(e->flags & EF_DISABLED)) && e->side != self->side && e->health > 0 && canAttack(e)) + if (canAttack(e)) { dist = getDistance(self->x, self->y, e->x, e->y); @@ -317,7 +318,15 @@ static void findTarget(void) static int canAttack(Entity *e) { - self->selectedGunType = self->guns[0].type; + if (!e->active || e->side == self->side || e->health <= 0) + { + return 0; + } + + if (!(e->flags & EF_TAKES_DAMAGE)) + { + return 0; + } if (!(e->flags & EF_AI_TARGET)) { @@ -330,6 +339,13 @@ static int canAttack(Entity *e) } } + return selectWeaponForTarget(e); +} + +static int selectWeaponForTarget(Entity *e) +{ + self->selectedGunType = self->guns[0].type; + if (e->flags & EF_MUST_DISABLE) { if (e->systemPower > 0) @@ -437,7 +453,7 @@ static void preAttack(void) if (!(self->aiFlags & AIF_MISSILE_BOAT)) { /* force weapon selection, otherwise we'll keep using lasers / mag */ - canAttack(self->target); + selectWeaponForTarget(self->target); if (self->guns[0].type && (self->missiles == 0 || rand() % 50 > 0)) { From 8705337e2ad3e655fb9b070d78954a7b531a2806 Mon Sep 17 00:00:00 2001 From: Steve Date: Tue, 29 Mar 2016 07:19:39 +0100 Subject: [PATCH 06/26] Show number of conditions on HUD, as well as objectives. --- src/battle/hud.c | 2 +- src/battle/objectives.c | 6 +++++- src/structs.h | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/battle/hud.c b/src/battle/hud.c index eca800b..738a69d 100644 --- a/src/battle/hud.c +++ b/src/battle/hud.c @@ -409,7 +409,7 @@ static void drawObjectives(void) if (!game.currentMission->challengeData.isChallenge) { blit(objectives, (SCREEN_WIDTH / 2) - 50, 14, 0); - drawText(SCREEN_WIDTH / 2, 10, 16, TA_CENTER, colors.white, "%d / %d", battle.numObjectivesComplete, battle.numObjectivesTotal); + drawText(SCREEN_WIDTH / 2, 10, 16, TA_CENTER, colors.white, "%d / %d", battle.numObjectivesComplete, (battle.numObjectivesTotal + battle.numConditions)); } else { diff --git a/src/battle/objectives.c b/src/battle/objectives.c index 122b7e0..c4f46e6 100644 --- a/src/battle/objectives.c +++ b/src/battle/objectives.c @@ -26,7 +26,7 @@ void doObjectives(void) int numHiddenObjectives; Objective *o; - battle.numObjectivesComplete = battle.numObjectivesTotal = 0; + battle.numObjectivesComplete = battle.numObjectivesTotal = battle.numConditions = 0; objectiveFailed = 0; numHiddenObjectives = 0; @@ -38,6 +38,10 @@ void doObjectives(void) { battle.numObjectivesTotal++; } + else + { + battle.numConditions++; + } } else { diff --git a/src/structs.h b/src/structs.h index 65a9e74..7e462bc 100644 --- a/src/structs.h +++ b/src/structs.h @@ -339,7 +339,7 @@ typedef struct { int ecmTimer; int radarRange; int numPlayerGuns; - int numObjectivesComplete, numObjectivesTotal; + int numObjectivesComplete, numObjectivesTotal, numConditions; Entity *missionTarget; Entity *jumpgate; SDL_Texture *background, *planetTexture; From 6016e46c3704b6e10aba8a1a486d0ade282dbb9d Mon Sep 17 00:00:00 2001 From: Steve Date: Tue, 29 Mar 2016 21:57:02 +0100 Subject: [PATCH 07/26] Mission tweaks. --- .../aster/01 - return to aster #1.json | 46 +++++++++++++++++-- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/data/missions/aster/01 - return to aster #1.json b/data/missions/aster/01 - return to aster #1.json index e476c6e..d454993 100644 --- a/data/missions/aster/01 - return to aster #1.json +++ b/data/missions/aster/01 - return to aster #1.json @@ -53,7 +53,7 @@ "x" : 25, "y" : 25, "number" : 6, - "aiFlags" : "+AIF_MOVES_TO_LEADER" + "aiFlags" : "AIF_MOVES_TO_LEADER+AIF_UNLIMITED_RANGE+AIF_DEFENSIVE" }, { "groupName" : "ShuttleTug", @@ -62,7 +62,7 @@ "x" : 25, "y" : 25, "number" : 6, - "aiFlags" : "+AIF_MOVES_TO_LEADER" + "aiFlags" : "AIF_MOVES_TO_LEADER+AIF_UNLIMITED_RANGE+AIF_DEFENSIVE" }, { "types" : "Thunderhead;Jackal;Sphinx", @@ -72,6 +72,28 @@ "number" : 4, "flags" : "+EF_AI_LEADER", "aiFlags" : "+AIF_UNLIMITED_RANGE" + }, + { + "groupName" : "Rebels", + "types" : "Razor", + "side" : "SIDE_REBEL", + "x" : 10, + "y" : 51, + "number" : 4, + "aiFlags" : "+AIF_UNLIMITED_RANGE", + "scatter" : 500, + "active" : 0 + }, + { + "groupName" : "Rebels", + "types" : "Khepri", + "side" : "SIDE_REBEL", + "x" : 10, + "y" : 51, + "number" : 8, + "aiFlags" : "+AIF_UNLIMITED_RANGE", + "scatter" : 500, + "active" : 0 } ], "capitalShips" : [ @@ -80,7 +102,7 @@ "types" : "CSN Corvette 01", "side" : "SIDE_ALLIES", "x" : 10, - "y" : 40, + "y" : 37, "flags" : "+EF_AI_TARGET+EF_DISABLED+EF_MISSION_TARGET" } ], @@ -96,7 +118,7 @@ ] }, { - "function" : "ENEMIES_DESTROYED 16", + "function" : "ENEMIES_KILLED 16", "lines" : [ "WAIT 2", "MSG_BOX Black;Florin, Pandoran vessels have been dealt with.", @@ -108,12 +130,26 @@ "MSG_BOX CSN Florin;Negative. These appear to be non-aligned forces, fighters and bombers.", "WAIT_MSG_BOX", "WAIT 5", - "ACTIVATE_ENTITY_GROUP Rebels", + "ACTIVATE_ENTITY_GROUPS Rebels", "MSG_BOX CSN Florin;Incoming forces are on intercept vectors. We only need a few more minutes.", "MSG_BOX Black;On it.", "WAIT_MSG_BOX", "ACTIVATE_OBJECTIVES Defeat rebel forces" ] + }, + { + "function" : "OBJECTIVES_COMPLETE 2", + "lines" : [ + "WAIT 2", + "MSG_BOX Black;Looks like that's all of them.", + "MSG_BOX CSN Florin;Those were Nation of Tzac fighters. We've heard reports of them being active in some Confederation systems.", + "MSG_BOX Black;Would appear that Crystabelle is finally ready to make good on all her threats. Great, so now we have both her AND the Pandorans to deal with.", + "MSG_BOX CSN Florin;It never rains ...", + "MSG_BOX CSN Florin;We're starting systems up again. Once we've completed pre-jump checks we're heading for Temper. Thank you for your assistance.", + "MSG_BOX Black;We'll meet you there.", + "WAIT_MSG_BOX", + "COMPLETE_MISSION" + ] } ] } From 52691f7be5ef1963f117782f3425834a815c7963 Mon Sep 17 00:00:00 2001 From: Steve Date: Tue, 29 Mar 2016 22:45:46 +0100 Subject: [PATCH 08/26] Enable AI flags to focus on targets. --- src/battle/ai.c | 15 +++++++++++---- src/defs.h | 1 + src/system/lookup.c | 1 + 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/battle/ai.c b/src/battle/ai.c index 11d5e55..9212c17 100644 --- a/src/battle/ai.c +++ b/src/battle/ai.c @@ -332,13 +332,15 @@ static int canAttack(Entity *e) { if (e->aiFlags & (AIF_AVOIDS_COMBAT | AIF_EVADE) || e->flags & EF_SECONDARY_TARGET) { - if (rand() % 5) - { - return 0; - } + return !(rand() % 5); } } + if ((self->aiFlags & AIF_TARGET_FOCUS) && (!(e->flags & EF_AI_TARGET))) + { + return 0; + } + return selectWeaponForTarget(e); } @@ -578,6 +580,11 @@ static int nearEnemies(void) { if ((e->flags & EF_TAKES_DAMAGE) && e->side != self->side && !(e->flags & EF_DISABLED)) { + if ((self->aiFlags & AIF_TARGET_FOCUS) && (e->flags & EF_AI_TARGET)) + { + continue; + } + if (getDistance(e->x, e->y, self->x, self->y) < 1000) { self->targetLocation.x += e->x; diff --git a/src/defs.h b/src/defs.h index 1ac1255..3f83cd1 100644 --- a/src/defs.h +++ b/src/defs.h @@ -115,6 +115,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define AIF_EVADE (2 << 13) #define AIF_WANDERS (2 << 14) #define AIF_COVERS_RETREAT (2 << 15) +#define AIF_TARGET_FOCUS (2 << 16) /* player abilities */ #define BOOST_RECHARGE_TIME (FPS * 7) diff --git a/src/system/lookup.c b/src/system/lookup.c index c7e7d36..02bcb85 100644 --- a/src/system/lookup.c +++ b/src/system/lookup.c @@ -79,6 +79,7 @@ void initLookups(void) addLookup("AIF_MOVES_TO_LEADER", AIF_MOVES_TO_LEADER); addLookup("AIF_WANDERS", AIF_WANDERS); addLookup("AIF_COVERS_RETREAT", AIF_COVERS_RETREAT); + addLookup("AIF_TARGET_FOCUS", AIF_TARGET_FOCUS); addLookup("DT_ANY", DT_ANY); addLookup("DT_NO_SPIN", DT_NO_SPIN); From 510bd3da00e46c43481720c06f14a11dd9af368e Mon Sep 17 00:00:00 2001 From: Steve Date: Tue, 29 Mar 2016 22:46:07 +0100 Subject: [PATCH 09/26] AI target focus for bombers. --- data/missions/aster/01 - return to aster #1.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/missions/aster/01 - return to aster #1.json b/data/missions/aster/01 - return to aster #1.json index d454993..9fb20a8 100644 --- a/data/missions/aster/01 - return to aster #1.json +++ b/data/missions/aster/01 - return to aster #1.json @@ -91,7 +91,7 @@ "x" : 10, "y" : 51, "number" : 8, - "aiFlags" : "+AIF_UNLIMITED_RANGE", + "aiFlags" : "+AIF_UNLIMITED_RANGE+AIF_TARGET_FOCUS", "scatter" : 500, "active" : 0 } From 3646a9326ad38437957e5f5a55971527766629c9 Mon Sep 17 00:00:00 2001 From: Steve Date: Wed, 30 Mar 2016 07:22:58 +0100 Subject: [PATCH 10/26] Start of mines. --- common.mk | 2 +- gfx/entities/mine.png | Bin 0 -> 381 bytes src/battle/effects.c | 30 +++++++++++++++++++ src/battle/mine.c | 66 ++++++++++++++++++++++++++++++++++++++++++ src/battle/mine.h | 29 +++++++++++++++++++ src/defs.h | 1 + src/galaxy/mission.c | 4 +++ src/galaxy/mission.h | 1 + src/system/lookup.c | 1 + 9 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 gfx/entities/mine.png create mode 100644 src/battle/mine.c create mode 100644 src/battle/mine.h diff --git a/common.mk b/common.mk index 84a8ad0..e79496f 100644 --- a/common.mk +++ b/common.mk @@ -19,7 +19,7 @@ OBJS += hud.o OBJS += i18n.o init.o input.o io.o items.o OBJS += jumpgate.o OBJS += load.o locations.o lookup.o -OBJS += main.o messageBox.o mission.o missionInfo.o modalDialog.o +OBJS += main.o messageBox.o mine.o mission.o missionInfo.o modalDialog.o OBJS += objectives.o options.o OBJS += player.o OBJS += quadtree.o diff --git a/gfx/entities/mine.png b/gfx/entities/mine.png new file mode 100644 index 0000000000000000000000000000000000000000..bc1df1016af892f0bc20a5976dcc34727981d7bf GIT binary patch literal 381 zcmeAS@N?(olHy`uVBq!ia0vp^;vmey1|%P7U0DF6*pj^6T^Rm@;DWu&Cj&(|3p^r= z85p>QL70(Y)*K0-AbW|YuPgflW;r%~%{PI<{y-tg64!_l=ltB<)VvY~=c3falGGH1 z^30M91$R&1fbd2>kX=tbT^vI^j&BXM7HTpOxifv^bmj-F^IByXr1x;e1>`yAr%7;4 zk$w&k zoyj8cP0sf!YA1%9mu3I} literal 0 HcmV?d00001 diff --git a/src/battle/effects.c b/src/battle/effects.c index 8b71890..f3684e8 100644 --- a/src/battle/effects.c +++ b/src/battle/effects.c @@ -284,6 +284,36 @@ void addSmallExplosion(void) } } +void addMineExplosion(void) +{ + int i; + Effect *e; + + for (i = 0 ; i < 16 ; i++) + { + e = malloc(sizeof(Effect)); + memset(e, 0, sizeof(Effect)); + battle.effectTail->next = e; + battle.effectTail = e; + + e->type = EFFECT_TEXTURE; + + e->x = self->x + rand() % 16 - rand() % 16; + e->y = self->y + rand() % 16 - rand() % 16; + e->texture = explosionTexture; + e->size = 32 + (rand() % 32); + e->r = 255; + + setRandomFlameHue(e); + + e->a = 32 + (rand() % 192); + e->health = e->a; + + e->x -= e->size / 2; + e->y -= e->size / 2; + } +} + void addLargeExplosion(void) { int i; diff --git a/src/battle/mine.c b/src/battle/mine.c new file mode 100644 index 0000000..4f673f7 --- /dev/null +++ b/src/battle/mine.c @@ -0,0 +1,66 @@ +/* +Copyright (C) 2015-2016 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "mine.h" + +static void think(void); +static void lookForFighters(void); + +Entity *spawnMine(void) +{ + Entity *mine = spawnEntity(); + + mine->type = ET_MINE; + mine->health = mine->maxHealth = 1; + mine->texture = getTexture("gfx/entities/mine.png"); + mine->action = think; + + return mine; +} + +static void think(void) +{ + self->angle += 0.1; + + if (self->angle >= 360) + { + self->angle -= 360; + } + + lookForFighters(); +} + +static void lookForFighters(void) +{ + Entity *e, **candidates; + int i; + + candidates = getAllEntsWithin(self->x - (self->w / 2), self->y - (self->h / 2), self->w, self->h, self); + + for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) + { + if (e->health > 0 && e->type == ET_FIGHTER && getDistance(self->x, self->y, e->x, e->y) <= 128) + { + self->health = 0; + + addMineExplosion(); + } + } +} diff --git a/src/battle/mine.h b/src/battle/mine.h new file mode 100644 index 0000000..2eef022 --- /dev/null +++ b/src/battle/mine.h @@ -0,0 +1,29 @@ +/* +Copyright (C) 2015-2016 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + +extern Entity *spawnEntity(void); +extern SDL_Texture *getTexture(char *filename); +extern Entity **getAllEntsWithin(int x, int y, int w, int h, Entity *ignore); +extern int getDistance(int x1, int y1, int x2, int y2); +extern void addMineExplosion(void); + +extern Entity *self; diff --git a/src/defs.h b/src/defs.h index 3f83cd1..7470e83 100644 --- a/src/defs.h +++ b/src/defs.h @@ -151,6 +151,7 @@ enum ET_ITEM, ET_WAYPOINT, ET_JUMPGATE, + ET_MINE, ET_CAPITAL_SHIP_GUN, ET_CAPITAL_SHIP_COMPONENT, ET_CAPITAL_SHIP_ENGINE, diff --git a/src/galaxy/mission.c b/src/galaxy/mission.c index 4da86a0..66ac781 100644 --- a/src/galaxy/mission.c +++ b/src/galaxy/mission.c @@ -351,6 +351,10 @@ static void loadEntities(cJSON *node) case ET_JUMPGATE: e = spawnJumpgate(); break; + + case ET_MINE: + e = spawnMine(); + break; default: printf("Error: Unhandled entity type: %s\n", cJSON_GetObjectItem(node, "type")->valuestring); diff --git a/src/galaxy/mission.h b/src/galaxy/mission.h index 420bafd..aa13bd7 100644 --- a/src/galaxy/mission.h +++ b/src/galaxy/mission.h @@ -57,6 +57,7 @@ extern void loadFighters(cJSON *node); extern void loadItems(cJSON *node); extern void loadLocations(cJSON *node); extern void loadSpawners(cJSON *node); +extern Entity *spawnMine(void); extern Battle battle; extern Dev dev; diff --git a/src/system/lookup.c b/src/system/lookup.c index 02bcb85..0bf0e78 100644 --- a/src/system/lookup.c +++ b/src/system/lookup.c @@ -45,6 +45,7 @@ void initLookups(void) addLookup("ET_WAYPOINT", ET_WAYPOINT); addLookup("ET_JUMPGATE", ET_JUMPGATE); addLookup("ET_CAPITAL_SHIP", ET_CAPITAL_SHIP); + addLookup("ET_MINE", ET_MINE); addLookup("EF_NO_KILL", EF_NO_KILL); addLookup("EF_DISABLED", EF_DISABLED); From daa8eff104e078175a4111b293de2320e74cdf19 Mon Sep 17 00:00:00 2001 From: Steve Date: Wed, 30 Mar 2016 22:41:34 +0100 Subject: [PATCH 11/26] Mines have a short radar range. --- src/battle/mine.c | 12 ++++++-- src/battle/radar.c | 76 +++++++++++++++++++++++++--------------------- src/defs.h | 37 +++++++++++----------- 3 files changed, 71 insertions(+), 54 deletions(-) diff --git a/src/battle/mine.c b/src/battle/mine.c index 4f673f7..0100c23 100644 --- a/src/battle/mine.c +++ b/src/battle/mine.c @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "mine.h" static void think(void); +static void die(void); static void lookForFighters(void); Entity *spawnMine(void) @@ -31,6 +32,8 @@ Entity *spawnMine(void) mine->health = mine->maxHealth = 1; mine->texture = getTexture("gfx/entities/mine.png"); mine->action = think; + mine->die = die; + mine->flags = EF_TAKES_DAMAGE+EF_SHORT_RADAR_RANGE; return mine; } @@ -47,6 +50,13 @@ static void think(void) lookForFighters(); } +static void die(void) +{ + addMineExplosion(); + + self->alive = ALIVE_DEAD; +} + static void lookForFighters(void) { Entity *e, **candidates; @@ -59,8 +69,6 @@ static void lookForFighters(void) if (e->health > 0 && e->type == ET_FIGHTER && getDistance(self->x, self->y, e->x, e->y) <= 128) { self->health = 0; - - addMineExplosion(); } } } diff --git a/src/battle/radar.c b/src/battle/radar.c index cbe7fbf..2468f80 100644 --- a/src/battle/radar.c +++ b/src/battle/radar.c @@ -34,6 +34,7 @@ void drawRadar(void) { SDL_Rect r; Entity *e; + int dist, inRange; blit(radarTexture, SCREEN_WIDTH - 85, SCREEN_HEIGHT - 85, 1); @@ -43,45 +44,52 @@ void drawRadar(void) for (e = battle.entityHead.next ; e != NULL ; e = e->next) { - if (e->active && getDistance(e->x, e->y, player->x, player->y) / radarRanges[battle.radarRange] < 70) + dist = getDistance(e->x, e->y, player->x, player->y); + + if (e->active) { - r.x = SCREEN_WIDTH - 85; - r.y = SCREEN_HEIGHT - 85; + inRange = (!(e->flags & EF_SHORT_RADAR_RANGE)) ? (dist / radarRanges[battle.radarRange]) < 70 : dist < 500; - r.x -= (player->x - e->x) / radarRanges[battle.radarRange]; - r.y -= (player->y - e->y) / radarRanges[battle.radarRange]; - - r.x--; - r.y--; - - switch (e->side) + if (inRange) { - case SIDE_ALLIES: - SDL_SetRenderDrawColor(app.renderer, 0, 255, 0, 255); - break; - - case SIDE_PIRATE: - case SIDE_PANDORAN: - case SIDE_REBEL: - SDL_SetRenderDrawColor(app.renderer, 255, 0, 0, 255); - break; - - case SIDE_NONE: + r.x = SCREEN_WIDTH - 85; + r.y = SCREEN_HEIGHT - 85; + + r.x -= (player->x - e->x) / radarRanges[battle.radarRange]; + r.y -= (player->y - e->y) / radarRanges[battle.radarRange]; + + r.x--; + r.y--; + + switch (e->side) + { + case SIDE_ALLIES: + SDL_SetRenderDrawColor(app.renderer, 0, 255, 0, 255); + break; + + case SIDE_PIRATE: + case SIDE_PANDORAN: + case SIDE_REBEL: + SDL_SetRenderDrawColor(app.renderer, 255, 0, 0, 255); + break; + + case SIDE_NONE: + SDL_SetRenderDrawColor(app.renderer, 255, 255, 255, 255); + break; + } + + if (e == player->target) + { + SDL_SetRenderDrawColor(app.renderer, 255, 255, 0, 255); + } + + if (e == battle.missionTarget) + { SDL_SetRenderDrawColor(app.renderer, 255, 255, 255, 255); - break; + } + + SDL_RenderFillRect(app.renderer, &r); } - - if (e == player->target) - { - SDL_SetRenderDrawColor(app.renderer, 255, 255, 0, 255); - } - - if (e == battle.missionTarget) - { - SDL_SetRenderDrawColor(app.renderer, 255, 255, 255, 255); - } - - SDL_RenderFillRect(app.renderer, &r); } } } diff --git a/src/defs.h b/src/defs.h index 7470e83..a9bad27 100644 --- a/src/defs.h +++ b/src/defs.h @@ -79,24 +79,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define BF_SHIELD_DAMAGE (2 << 2) #define BF_EXPLODES (2 << 3) -#define EF_NONE 0 -#define EF_NO_KILL (2 << 0) -#define EF_DISABLED (2 << 1) -#define EF_IMMORTAL (2 << 2) -#define EF_MISSION_TARGET (2 << 3) -#define EF_NO_MT_BOX (2 << 4) -#define EF_HAS_ROPE (2 << 5) -#define EF_COLLECTS_ITEMS (2 << 6) -#define EF_MUST_DISABLE (2 << 7) -#define EF_RETREATING (2 << 8) -#define EF_NO_EPIC (2 << 9) -#define EF_STATIC (2 << 10) -#define EF_TAKES_DAMAGE (2 << 11) -#define EF_SECONDARY_TARGET (2 << 12) -#define EF_AI_TARGET (2 << 13) -#define EF_AI_LEADER (2 << 14) -#define EF_ROPED_ATTACHED (2 << 15) -#define EF_NO_KILL_INC (2 << 16) +#define EF_NONE 0 +#define EF_NO_KILL (2 << 0) +#define EF_DISABLED (2 << 1) +#define EF_IMMORTAL (2 << 2) +#define EF_MISSION_TARGET (2 << 3) +#define EF_NO_MT_BOX (2 << 4) +#define EF_HAS_ROPE (2 << 5) +#define EF_COLLECTS_ITEMS (2 << 6) +#define EF_MUST_DISABLE (2 << 7) +#define EF_RETREATING (2 << 8) +#define EF_NO_EPIC (2 << 9) +#define EF_STATIC (2 << 10) +#define EF_TAKES_DAMAGE (2 << 11) +#define EF_SECONDARY_TARGET (2 << 12) +#define EF_AI_TARGET (2 << 13) +#define EF_AI_LEADER (2 << 14) +#define EF_ROPED_ATTACHED (2 << 15) +#define EF_NO_KILL_INC (2 << 16) +#define EF_SHORT_RADAR_RANGE (2 << 17) #define AIF_NONE 0 #define AIF_FOLLOWS_PLAYER (2 << 0) From 3bf73b5d7012438f2a426a9840b0d7a0dac2a2df Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 10:49:41 +0100 Subject: [PATCH 12/26] Updates to mines. --- README.md | 3 + gfx/entities/mineWarning.png | Bin 0 -> 988 bytes .../172870__escortmarius__carbidexplosion.ogg | Bin 0 -> 17644 bytes sound/254174__kwahmah-02__s.ogg | Bin 0 -> 5373 bytes src/battle/effects.c | 20 +++++ src/battle/mine.c | 78 ++++++++++++++++-- src/battle/mine.h | 6 ++ src/battle/player.c | 2 +- src/defs.h | 3 + src/system/sound.c | 2 + 10 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 gfx/entities/mineWarning.png create mode 100644 sound/172870__escortmarius__carbidexplosion.ogg create mode 100644 sound/254174__kwahmah-02__s.ogg diff --git a/README.md b/README.md index 0595634..d958f40 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,9 @@ CC BY-NC-SA 3.0, with the following attribution: Copyright 2015-2016, Stephen J * 251431__onlytheghosts__fusion-gun-flash0-by-onlytheghosts.ogg - fusion-gun_flash0_by_OnlyTheGhosts.wav, by OnlyTheGhosts - https://freesound.org/people/OnlyTheGhosts/sounds/251431/ * 172591__timbre__zapitydooda.ogg - d1clsstf.wav, by wildweasel - https://freesound.org/people/wildweasel/sounds/39030/ * 39030__wildweasel__d1clsstf.ogg - push_button_switch_07.wav, by joedeshon - https://freesound.org/people/joedeshon/sounds/139061/ +* 254174__kwahmah-02__s.ogg - s.wav, by kwahmah_02 - https://freesound.org/people/kwahmah_02/sounds/254174/ +* 172870__escortmarius__carbidexplosion.ogg - carbidexplosion.wav, by escortmarius - https://freesound.org/people/escortmarius/sounds/172870/ + ### MUSIC diff --git a/gfx/entities/mineWarning.png b/gfx/entities/mineWarning.png new file mode 100644 index 0000000000000000000000000000000000000000..8b78308fb9b299ebdb85bd2e9d9f2eb4ef09c7f6 GIT binary patch literal 988 zcmV<210(#2P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00TrxL_t(Y$F-HsZ(CIm#eZ|} zeRdMZalS}sf@HgDtHy~a3y|1##g-+oDD*!=LKPB7toRSIM6f_rW0eHe2@(xTLsEam zj^Dd?SokI~iIb)hj5NFZ&YYPy=M20>C@B9|)M_<-8v^D{tQ16HQemd(Jqjg-X@z85 zaRIpmE+C`KBIqoz5_5GaO#xPcTfi-a1%=!haJ^oa(PA>L`c}Q32j+niQ2eS~{y9;_ z0s%-x_-1eKW1s`HKDvMZk6)fYzl0@Y#*jR`dv~z8v-AF!F2uy}RP8F+)iZBqN zFGAN^TE_50qfrG8WmxPy+?X-XZtm=CJT8}?&3n&`_Y^{4LKUNm0s~_>5h1UNwU*dr zrZ5l~jAgD+0N#C6sr){lWh{74$$N_4GZ6wVj-|A`gj-l-uhrtWqa%)-4d5?< zzpr9m0HzBePz-^h_snJ)rN};~isW*vmS$P3Rw*1D@bd7GzV~O}PAN16vWu%|fczJg z%CGr2=Ryd~gutBlypv@tXBi9qKJNIK-u^zc+f0SPq$-cg<)45F;`Ur*?f{nni7JUI zxe%C$Mdspo`o_@Q-{)1g%gZz)(Lkb#Q$5Ex2UO7YT8$4vU^&ZJN>c2D8V=zPI;YH{hLoNjDaAg^Y&@+a1 zEbwF~pw~d_CdRc0%zs|3ZWp{~Qk8s^|Cw=}8bj9@zTMqje|YcS*5>whPDbW^34GKx zqutH`)1OtVTS;6^1u_x7Ycw95xgzj-y;e&vTJE)1Mj@{-r?8?>{^ZUbRj4Sur?99n z^~OteliR3}JXl*(g+#}U^U5^pqm~s~PdMcO0000< KMNUMnLSTZ`Vz(mz literal 0 HcmV?d00001 diff --git a/sound/172870__escortmarius__carbidexplosion.ogg b/sound/172870__escortmarius__carbidexplosion.ogg new file mode 100644 index 0000000000000000000000000000000000000000..e65522f06554873dba184c5ce92f0c51e129f0e2 GIT binary patch literal 17644 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 literal 0 HcmV?d00001 diff --git a/sound/254174__kwahmah-02__s.ogg b/sound/254174__kwahmah-02__s.ogg new file mode 100644 index 0000000000000000000000000000000000000000..8ef31a62bd85d6ba1cdfa1887369200fc85c374c GIT binary patch literal 5373 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 -= e->size / 2; e->y -= e->size / 2; } + + e = malloc(sizeof(Effect)); + + memset(e, 0, sizeof(Effect)); + battle.effectTail->next = e; + battle.effectTail = e; + + e->type = EFFECT_HALO; + e->x = self->x; + e->y = self->y; + e->size = 32; + e->scaleAmount = 2; + e->texture = haloTexture; + + e->r = 255; + e->g = 255; + e->b = 255; + e->a = 128; + + e->health = 128; } void addLargeExplosion(void) diff --git a/src/battle/mine.c b/src/battle/mine.c index 0100c23..6d4403f 100644 --- a/src/battle/mine.c +++ b/src/battle/mine.c @@ -23,6 +23,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static void think(void); static void die(void); static void lookForFighters(void); +static void doSplashDamage(void); + +static SDL_Texture *mineWarning; +static SDL_Texture *mineNormal; Entity *spawnMine(void) { @@ -30,16 +34,22 @@ Entity *spawnMine(void) mine->type = ET_MINE; mine->health = mine->maxHealth = 1; + mine->systemPower = SYSTEM_POWER; mine->texture = getTexture("gfx/entities/mine.png"); mine->action = think; mine->die = die; - mine->flags = EF_TAKES_DAMAGE+EF_SHORT_RADAR_RANGE; + mine->flags = EF_TAKES_DAMAGE+EF_SHORT_RADAR_RANGE+EF_NO_TARGET; + + mineNormal = getTexture("gfx/entities/mine.png"); + mineWarning = getTexture("gfx/entities/mineWarning.png"); return mine; } static void think(void) { + self->texture = mineNormal; + self->angle += 0.1; if (self->angle >= 360) @@ -48,13 +58,13 @@ static void think(void) } lookForFighters(); -} - -static void die(void) -{ - addMineExplosion(); - self->alive = ALIVE_DEAD; + if (self->systemPower < SYSTEM_POWER && SDL_GetTicks() % 150 < 75) + { + playBattleSound(SND_MINE_WARNING, self->x, self->y); + + self->texture = mineWarning; + } } static void lookForFighters(void) @@ -62,13 +72,63 @@ static void lookForFighters(void) Entity *e, **candidates; int i; + candidates = getAllEntsWithin(self->x - (self->w / 2) - DAMAGE_RANGE, self->y - (self->h / 2) - DAMAGE_RANGE, self->w + DAMAGE_RANGE, self->h + DAMAGE_RANGE, self); + + for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) + { + if (e->health > 0 && e->type == ET_FIGHTER && getDistance(self->x, self->y, e->x, e->y) <= TRIGGER_RANGE) + { + self->systemPower--; + + if (self->systemPower <= 0) + { + self->health = 0; + } + + return; + } + } + + self->systemPower = SYSTEM_POWER; +} + + +static void die(void) +{ + addMineExplosion(); + + doSplashDamage(); + + playBattleSound(SND_EXPLOSION_5, self->x, self->y); + + self->alive = ALIVE_DEAD; +} + +static void doSplashDamage(void) +{ + Entity *e, **candidates; + int i, dist; + float damage, percent; + candidates = getAllEntsWithin(self->x - (self->w / 2), self->y - (self->h / 2), self->w, self->h, self); for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) { - if (e->health > 0 && e->type == ET_FIGHTER && getDistance(self->x, self->y, e->x, e->y) <= 128) + if (e->health > 0 && e->type == ET_FIGHTER) { - self->health = 0; + dist = getDistance(self->x, self->y, e->x, e->y); + + if (dist <= DAMAGE_RANGE) + { + percent = dist; + percent /= DAMAGE_RANGE; + percent = 1 - percent; + + damage = 100; + damage *= percent; + + damageFighter(e, damage, 0); + } } } } diff --git a/src/battle/mine.h b/src/battle/mine.h index 2eef022..71299db 100644 --- a/src/battle/mine.h +++ b/src/battle/mine.h @@ -20,10 +20,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../common.h" +#define TRIGGER_RANGE 150 +#define DAMAGE_RANGE 255 +#define SYSTEM_POWER 75 + extern Entity *spawnEntity(void); extern SDL_Texture *getTexture(char *filename); extern Entity **getAllEntsWithin(int x, int y, int w, int h, Entity *ignore); extern int getDistance(int x1, int y1, int x2, int y2); extern void addMineExplosion(void); +extern void damageFighter(Entity *e, int amount, long flags); +extern void playBattleSound(int id, int x, int y); extern Entity *self; diff --git a/src/battle/player.c b/src/battle/player.c index a47e192..221326a 100644 --- a/src/battle/player.c +++ b/src/battle/player.c @@ -480,7 +480,7 @@ static void selectTarget(void) for (e = battle.entityHead.next ; e != NULL ; e = e->next) { - if (e->active && e != player && (e->flags & EF_TAKES_DAMAGE) && e->side != player->side && e->alive == ALIVE_ALIVE && e->systemPower > 0 && i < MAX_SELECTABLE_TARGETS) + if (e->active && e != player && (e->flags & EF_TAKES_DAMAGE) && (!(e->flags & EF_NO_TARGET)) && e->side != player->side && e->alive == ALIVE_ALIVE && e->systemPower > 0 && i < MAX_SELECTABLE_TARGETS) { dist = getDistance(self->x, self->y, e->x, e->y); if (dist < closest) diff --git a/src/defs.h b/src/defs.h index a9bad27..605874b 100644 --- a/src/defs.h +++ b/src/defs.h @@ -98,6 +98,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define EF_ROPED_ATTACHED (2 << 15) #define EF_NO_KILL_INC (2 << 16) #define EF_SHORT_RADAR_RANGE (2 << 17) +#define EF_NO_TARGET (2 << 18) #define AIF_NONE 0 #define AIF_FOLLOWS_PLAYER (2 << 0) @@ -228,6 +229,7 @@ enum SND_EXPLOSION_2, SND_EXPLOSION_3, SND_EXPLOSION_4, + SND_EXPLOSION_5, SND_GET_ITEM, SND_MISSILE, SND_INCOMING, @@ -238,6 +240,7 @@ enum SND_POWER_DOWN, SND_BOOST, SND_RADIO, + SND_MINE_WARNING, SND_GUI_CLICK, SND_GUI_SELECT, SND_GUI_CLOSE, diff --git a/src/system/sound.c b/src/system/sound.c index 3b122b2..a2c68d3 100644 --- a/src/system/sound.c +++ b/src/system/sound.c @@ -112,11 +112,13 @@ static void loadSounds(void) sounds[SND_EXPLOSION_2] = loadSound("sound/207322__animationisaac__short-explosion.ogg"); sounds[SND_EXPLOSION_3] = loadSound("sound/254071__tb0y298__firework-explosion.ogg"); sounds[SND_EXPLOSION_4] = loadSound("sound/47252__nthompson__bad-explosion.ogg"); + sounds[SND_EXPLOSION_5] = loadSound("sound/172870__escortmarius__carbidexplosion.ogg"); sounds[SND_JUMP] = loadSound("sound/276912__pauldihor__transform.ogg"); sounds[SND_ECM] = loadSound("sound/251431__onlytheghosts__fusion-gun-flash0-by-onlytheghosts.ogg"); sounds[SND_MAG_HIT] = loadSound("sound/172591__timbre__zapitydooda.ogg"); sounds[SND_POWER_DOWN] = loadSound("sound/39030__wildweasel__d1clsstf.ogg"); sounds[SND_SELECT_WEAPON] = loadSound("sound/329359__bassoonrckr__reed-guillotine.ogg"); + sounds[SND_MINE_WARNING] = loadSound("sound/254174__kwahmah-02__s.ogg"); sounds[SND_GUI_CLICK] = loadSound("sound/257786__xtrgamr__mouse-click.ogg"); sounds[SND_GUI_SELECT] = loadSound("sound/321104__nsstudios__blip2.ogg"); From 2308f6ff434ae73d4ef67bf3c19f0517a30753e5 Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 10:49:57 +0100 Subject: [PATCH 13/26] i18n updates. --- locale/tbftss.pot | 56 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/locale/tbftss.pot b/locale/tbftss.pot index e3de4ed..8c7afde 100644 --- a/locale/tbftss.pot +++ b/locale/tbftss.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: TBFTSS: The Pandoran War\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-03-27 11:09:14+0100\n" +"POT-Creation-Date: 2016-04-01 08:08:53+0100\n" "PO-Revision-Date: ???\n" "Last-Translator: ???\n" "Language-Team: ???\n" @@ -577,6 +577,54 @@ msgstr "" msgid "Okay, let's get home and report in." msgstr "" +msgid "Florin, this is Black of the Salty Wildcats, here to assist." +msgstr "" + +msgid "Glad to see you, Wildcats. The Pandorans arrived shortly before you did. We've got tugs and shuttles incoming." +msgstr "" + +msgid "Acknowledged, we'll secure the area while you get things up and running." +msgstr "" + +msgid "Florin, Pandoran vessels have been dealt with." +msgstr "" + +msgid "Many thanks, Wildcats. We've identified the cause of the power outage. Should be no more than a few minutes before we can restart all systems." +msgstr "" + +msgid "Wildcats, we're picking up an incoming squadron." +msgstr "" + +msgid "More Pandoran tugs?" +msgstr "" + +msgid "Negative. These appear to be non-aligned forces, fighters and bombers." +msgstr "" + +msgid "Incoming forces are on intercept vectors. We only need a few more minutes." +msgstr "" + +msgid "On it." +msgstr "" + +msgid "Looks like that's all of them." +msgstr "" + +msgid "Those were Nation of Tzac fighters. We've heard reports of them being active in some Confederation systems." +msgstr "" + +msgid "Would appear that Crystabelle is finally ready to make good on all her threats. Great, so now we have both her AND the Pandorans to deal with." +msgstr "" + +msgid "It never rains ..." +msgstr "" + +msgid "We're starting systems up again. Once we've completed pre-jump checks we're heading for Temper. Thank you for your assistance." +msgstr "" + +msgid "We'll meet you there." +msgstr "" + msgid "The day that we have feared and the events that we attempted to avert are now upon us - the Pandoran army has commenced its push beyond Mitikas space, and is beginning to assault neighbouring Independent star systems. We need to fight back, in order to protect Clarke from becoming underrun by this menace. Take heed: this will not be an easy battle, but we have little choice and must secure victory here today." msgstr "" @@ -661,9 +709,6 @@ msgstr "" msgid "Only way we'll find out is if we go to Kethlan, and I'm not keen on heading there anytime soon." msgstr "" -msgid "Looks like that's all of them." -msgstr "" - msgid "Chaz, anything?" msgstr "" @@ -910,9 +955,6 @@ msgstr "" msgid "Too early to speculate. We want you to disable and bring in one craft from each side. The rest, you can eliminate." msgstr "" -msgid "On it." -msgstr "" - msgid "This is Carr, reporting operation successful. Bagged us two squadron commanders." msgstr "" From e8f70072d579d13a1a6b7f74daca3316bd8f9dd8 Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 11:39:52 +0100 Subject: [PATCH 14/26] Don't cause damage to immortal fighters. --- src/battle/mine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle/mine.c b/src/battle/mine.c index 6d4403f..99e6265 100644 --- a/src/battle/mine.c +++ b/src/battle/mine.c @@ -114,7 +114,7 @@ static void doSplashDamage(void) for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) { - if (e->health > 0 && e->type == ET_FIGHTER) + if (e->health > 0 && e->type == ET_FIGHTER && !(e->flags & EF_IMMORTAL)) { dist = getDistance(self->x, self->y, e->x, e->y); From 58fb3e911bac80204a82aedebb8a746ee7d2521a Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 11:40:09 +0100 Subject: [PATCH 15/26] Tell AI to avoid mines. --- src/battle/ai.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/battle/ai.c b/src/battle/ai.c index 9212c17..329232e 100644 --- a/src/battle/ai.c +++ b/src/battle/ai.c @@ -37,6 +37,7 @@ static int nearJumpgate(void); static void moveToJumpgate(void); static int nearEnemies(void); static int nearItems(void); +static int nearMines(void); static void moveToItem(void); static int nearTowableCraft(void); static void moveToTowableCraft(void); @@ -64,6 +65,11 @@ void doAI(void) return; } + if (nearMines()) + { + return; + } + if ((self->aiFlags & AIF_GOAL_JUMPGATE) && nearJumpgate()) { /* near jumpgate, but you might decide to continue to fight, anyway */ @@ -612,6 +618,45 @@ static int nearEnemies(void) return 0; } +static int nearMines(void) +{ + int i, numMines; + Entity *e, **candidates; + + candidates = getAllEntsWithin(self->x - 500, self->y - 500, 1000, 1000, self); + + self->targetLocation.x = self->targetLocation.y = 0; + + numMines = 0; + + for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) + { + if (e->type == ET_MINE && getDistance(e->x, e->y, self->x, self->y) < 500) + { + self->targetLocation.x += e->x; + self->targetLocation.y += e->y; + numMines++; + } + } + + if (numMines) + { + self->targetLocation.x /= numMines; + self->targetLocation.y /= numMines; + + /* dodge slightly */ + self->targetLocation.x += (rand() % 100 - rand() % 100); + self->targetLocation.y += (rand() % 100 - rand() % 100); + + self->action = fleeEnemies; + self->aiActionTime = FPS * 2; + + return 1; + } + + return 0; +} + static void fleeEnemies(void) { int wantedAngle = 180 + getAngle(self->x, self->y, self->targetLocation.x, self->targetLocation.y); From d178134a00fc77e4aa9565d93f4e8c43160603cc Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 14:19:03 +0100 Subject: [PATCH 16/26] Allow AI to drop mines. --- src/battle/ai.c | 23 ++++++++++++++++++++++- src/battle/ai.h | 1 + src/defs.h | 1 + src/system/lookup.c | 1 + 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/battle/ai.c b/src/battle/ai.c index 329232e..5416d84 100644 --- a/src/battle/ai.c +++ b/src/battle/ai.c @@ -52,9 +52,15 @@ static void moveToLeader(void); static void wander(void); static void doWander(void); static int selectWeaponForTarget(Entity *e); +static void deployMine(void); void doAI(void) { + if (self->aiFlags & AIF_DROPS_MINES) + { + deployMine(); + } + if ((self->aiFlags & (AIF_AVOIDS_COMBAT | AIF_EVADE)) && nearEnemies()) { return; @@ -618,6 +624,21 @@ static int nearEnemies(void) return 0; } +static void deployMine(void) +{ + Entity *mine; + + if (!self->reload) + { + mine = spawnMine(); + mine->x = self->x; + mine->y = self->y; + mine->side = self->side; + + self->reload = FPS + (FPS * (rand() % 5)); + } +} + static int nearMines(void) { int i, numMines; @@ -631,7 +652,7 @@ static int nearMines(void) for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) { - if (e->type == ET_MINE && getDistance(e->x, e->y, self->x, self->y) < 500) + if (e->side != self->side && e->type == ET_MINE && getDistance(e->x, e->y, self->x, self->y) < 500) { self->targetLocation.x += e->x; self->targetLocation.y += e->y; diff --git a/src/battle/ai.h b/src/battle/ai.h index 9038b97..628088b 100644 --- a/src/battle/ai.h +++ b/src/battle/ai.h @@ -38,6 +38,7 @@ extern void applyFighterBrakes(void); extern void addHudMessage(SDL_Color c, char *format, ...); extern Entity **getAllEntsWithin(int x, int y, int w, int h, Entity *ignore); extern char *getTranslatedString(char *string); +extern Entity *spawnMine(void); extern Battle battle; extern Colors colors; diff --git a/src/defs.h b/src/defs.h index 605874b..cc7d658 100644 --- a/src/defs.h +++ b/src/defs.h @@ -118,6 +118,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define AIF_WANDERS (2 << 14) #define AIF_COVERS_RETREAT (2 << 15) #define AIF_TARGET_FOCUS (2 << 16) +#define AIF_DROPS_MINES (2 << 17) /* player abilities */ #define BOOST_RECHARGE_TIME (FPS * 7) diff --git a/src/system/lookup.c b/src/system/lookup.c index 0bf0e78..964129d 100644 --- a/src/system/lookup.c +++ b/src/system/lookup.c @@ -81,6 +81,7 @@ void initLookups(void) addLookup("AIF_WANDERS", AIF_WANDERS); addLookup("AIF_COVERS_RETREAT", AIF_COVERS_RETREAT); addLookup("AIF_TARGET_FOCUS", AIF_TARGET_FOCUS); + addLookup("AIF_DROPS_MINES", AIF_DROPS_MINES); addLookup("DT_ANY", DT_ANY); addLookup("DT_NO_SPIN", DT_NO_SPIN); From fc384452a2def94075a6d88e55ed22b2b8a51b3d Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 14:19:15 +0100 Subject: [PATCH 17/26] Reduced Shale fire rate. --- data/fighters/shale.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/fighters/shale.json b/data/fighters/shale.json index fcf041f..f8f5c09 100644 --- a/data/fighters/shale.json +++ b/data/fighters/shale.json @@ -3,7 +3,7 @@ "health" : 50, "shield" : 50, "speed" : 2, - "reloadTime" : 8, + "reloadTime" : 18, "shieldRechargeRate" : 20, "texture" : "gfx/fighters/shale.png", "guns" : [ From 1c0359d14f80ab01b67f3bc8b0595dc77a5ad8a8 Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 14:19:24 +0100 Subject: [PATCH 18/26] Made mine more visible. --- gfx/entities/mine.png | Bin 381 -> 702 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/gfx/entities/mine.png b/gfx/entities/mine.png index bc1df1016af892f0bc20a5976dcc34727981d7bf..c0135fc64acbb0467d85fbdb6450259c84868649 100644 GIT binary patch delta 636 zcmV-?0)zei0=@;1Dlu;WZvbz6r>i#r000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2jBz&3@`)O`R=NbTPJ@4CP_p=R7l6QRXc9mKoEU9GdIuy;$D@dMiprgVCCF^JcHT9 zK-@`z83=G1yH#a_I)DW@CvX5(vC~@tnSs2WM4Y)vvz#>Jnc{Fdtk)~iA$HuZP zr7|cBgc(%)r=PHFm9ep-Wm%dsOqmIn*b8Gg9OB)<0hUisST27;gfW}VOef|kqYYz{ zoH3!->%nzh3-piJY=C$u<;CGANV!UQII!&)$zOiU-A zd!DD!d~R-Tu1$WIhel!nyc#e7v#+>cCC}(#FViJ0J;DJ01>y=bjAAT*Z(i_ WP?j8@2x-><0000y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2jBx91`jFhQ4>#*TPJ@2~41QUiJYIr2&n-ikWqc0kNekX4V8yk~7!2>5NPuDJA)cON@zQ z6kmcv-gteHS3IPw2W1ecxLz5U~?+%raEf4Rw5d$F(e-SP|>`s}!bb z!Z^P1nP(^O5bInig-6q%ZCeb(%ZVio=ri-?zxgSpdCpS>*G(1JvFP6!cg^~)&NmUa z{ZL`c6&t}MYvz?|DyJvrs;(Uq6>g?(O0000< KMNUMnLSTZ)?uq>X From 994c0b55dd0dc1c3da7bdf6b8dce1383fab9bccb Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 14:19:55 +0100 Subject: [PATCH 19/26] Don't explode mine on owner. --- src/battle/mine.c | 21 +++++++++++++-------- src/battle/mine.h | 3 ++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/battle/mine.c b/src/battle/mine.c index 99e6265..332e447 100644 --- a/src/battle/mine.c +++ b/src/battle/mine.c @@ -25,23 +25,28 @@ static void die(void); static void lookForFighters(void); static void doSplashDamage(void); -static SDL_Texture *mineWarning; -static SDL_Texture *mineNormal; +static SDL_Texture *mineWarning = NULL; +static SDL_Texture *mineNormal = NULL; Entity *spawnMine(void) { Entity *mine = spawnEntity(); + + if (!mineNormal || !mineWarning) + { + mineNormal = getTexture("gfx/entities/mine.png"); + mineWarning = getTexture("gfx/entities/mineWarning.png"); + } mine->type = ET_MINE; mine->health = mine->maxHealth = 1; mine->systemPower = SYSTEM_POWER; - mine->texture = getTexture("gfx/entities/mine.png"); + mine->texture = mineNormal; mine->action = think; mine->die = die; - mine->flags = EF_TAKES_DAMAGE+EF_SHORT_RADAR_RANGE+EF_NO_TARGET; + mine->flags = EF_TAKES_DAMAGE+EF_NO_TARGET; - mineNormal = getTexture("gfx/entities/mine.png"); - mineWarning = getTexture("gfx/entities/mineWarning.png"); + SDL_QueryTexture(mine->texture, NULL, NULL, &mine->w, &mine->h); return mine; } @@ -59,7 +64,7 @@ static void think(void) lookForFighters(); - if (self->systemPower < SYSTEM_POWER && SDL_GetTicks() % 150 < 75) + if (self->systemPower < SYSTEM_POWER && battle.stats[STAT_TIME] % 8 < 4) { playBattleSound(SND_MINE_WARNING, self->x, self->y); @@ -76,7 +81,7 @@ static void lookForFighters(void) for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) { - if (e->health > 0 && e->type == ET_FIGHTER && getDistance(self->x, self->y, e->x, e->y) <= TRIGGER_RANGE) + if (e->side != self->side && e->health > 0 && e->type == ET_FIGHTER && getDistance(self->x, self->y, e->x, e->y) <= TRIGGER_RANGE) { self->systemPower--; diff --git a/src/battle/mine.h b/src/battle/mine.h index 71299db..6c613d9 100644 --- a/src/battle/mine.h +++ b/src/battle/mine.h @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define TRIGGER_RANGE 150 #define DAMAGE_RANGE 255 -#define SYSTEM_POWER 75 +#define SYSTEM_POWER 50 extern Entity *spawnEntity(void); extern SDL_Texture *getTexture(char *filename); @@ -32,4 +32,5 @@ extern void addMineExplosion(void); extern void damageFighter(Entity *e, int amount, long flags); extern void playBattleSound(int id, int x, int y); +extern Battle battle; extern Entity *self; From e2172a1789394a1cd1e263b43897c31b0e563a8d Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 14:20:03 +0100 Subject: [PATCH 20/26] Show mines on radar as white. --- src/battle/radar.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/battle/radar.c b/src/battle/radar.c index 2468f80..4032b3b 100644 --- a/src/battle/radar.c +++ b/src/battle/radar.c @@ -88,6 +88,11 @@ void drawRadar(void) SDL_SetRenderDrawColor(app.renderer, 255, 255, 255, 255); } + if (e->type == ET_MINE) + { + SDL_SetRenderDrawColor(app.renderer, 255, 255, 255, 255); + } + SDL_RenderFillRect(app.renderer, &r); } } From a913dc613b2fcd389a8587e827b0cb762073da87 Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 14:20:47 +0100 Subject: [PATCH 21/26] Set width and height of entities in spawn functions. --- src/battle/jumpgate.c | 2 ++ src/battle/waypoints.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/battle/jumpgate.c b/src/battle/jumpgate.c index 64c6365..8fd5ede 100644 --- a/src/battle/jumpgate.c +++ b/src/battle/jumpgate.c @@ -41,6 +41,8 @@ Entity *spawnJumpgate(void) portal = getTexture("gfx/entities/portal.png"); portalAngle = 0; + + SDL_QueryTexture(jumpgate->texture, NULL, NULL, &jumpgate->w, &jumpgate->h); return jumpgate; } diff --git a/src/battle/waypoints.c b/src/battle/waypoints.c index 70226d4..7f95402 100644 --- a/src/battle/waypoints.c +++ b/src/battle/waypoints.c @@ -45,6 +45,8 @@ Entity *spawnWaypoint(void) waypoint->action = think; waypoint->flags |= EF_NO_MT_BOX; + SDL_QueryTexture(waypoint->texture, NULL, NULL, &waypoint->w, &waypoint->h); + return waypoint; } From 26ed8dc3227ce0b63a11fc447c34ad49ec0a6e5b Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 14:21:11 +0100 Subject: [PATCH 22/26] Allow side to be set for entities (mostly applies to mines). --- src/galaxy/mission.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/galaxy/mission.c b/src/galaxy/mission.c index 66ac781..5ba64e9 100644 --- a/src/galaxy/mission.c +++ b/src/galaxy/mission.c @@ -311,7 +311,7 @@ static void loadEntities(cJSON *node) { Entity *e; char *name, *groupName; - int i, type, scatter, number, active, addFlags; + int i, type, scatter, number, active, addFlags, side; float x, y; long flags; @@ -334,6 +334,7 @@ static void loadEntities(cJSON *node) number = getJSONValue(node, "number", 1); active = getJSONValue(node, "active", 1); scatter = getJSONValue(node, "scatter", 1); + side = getJSONValue(node, "side", SIDE_NONE); if (cJSON_GetObjectItem(node, "flags")) { @@ -388,6 +389,8 @@ static void loadEntities(cJSON *node) e->x = x; e->y = y; + + e->side = side; if (scatter > 1) { @@ -396,8 +399,6 @@ static void loadEntities(cJSON *node) } e->active = active; - - SDL_QueryTexture(e->texture, NULL, NULL, &e->w, &e->h); } node = node->next; From 0985bcd0e99694f18e294b0819f65fe39e40bcd6 Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 14:21:26 +0100 Subject: [PATCH 23/26] Start of 2nd Aster mission. --- .../aster/02 - return to aster #2.json | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 data/missions/aster/02 - return to aster #2.json diff --git a/data/missions/aster/02 - return to aster #2.json b/data/missions/aster/02 - return to aster #2.json new file mode 100644 index 0000000..8389017 --- /dev/null +++ b/data/missions/aster/02 - return to aster #2.json @@ -0,0 +1,63 @@ +{ + "name" : "Mine Sweeper", + "description" : "", + "requires" : 33, + "background" : "gfx/backgrounds/background04.jpg", + "planet" : "gfx/planets/bluePlanet.png", + "music" : "music/battle/track-3.mp3", + "objectives" : [ + { + "description" : "Destroy all enemy forces", + "targetName" : "Enemy", + "targetValue" : 1, + "targetType" : "TT_DESTROY", + "isEliminateAll" : 1 + } + ], + "player" : { + "type" : "Ray", + "side" : "SIDE_ALLIES", + "pilot" : "1st Lt. Cora Pope", + "squadron" : "Midnight Runners", + "x" : 25, + "y" : 45 + }, + "fighters" : [ + { + "types" : "TAF", + "side" : "SIDE_ALLIES", + "x" : 25, + "y" : 45, + "number" : 3, + "scatter" : 500 + }, + { + "types" : "Khepri", + "side" : "SIDE_REBEL", + "x" : 25, + "y" : 30, + "number" : 5, + "scatter" : 4000, + "flags" : "+EF_AI_LEADER", + "aiFlags" : "+AIF_DROPS_MINES" + }, + { + "types" : "Shale", + "side" : "SIDE_REBEL", + "x" : 25, + "y" : 35, + "number" : 3, + "scatter" : 2500, + "aiFlags" : "+AIF_MOVES_TO_LEADER" + } + ], + "script" : [ + { + "function" : "TIME 2", + "lines" : [ + "MSG_BOX Pope;Watch out for those mines. They're on proximity triggers and have a large area of effect.", + "MSG_BOX Pope;Take them out from a distance, otherwise you'll be in trouble." + ] + } + ] +} From cfc41a624b26c5fdaad0338d596b9383269cebc2 Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 17:02:36 +0100 Subject: [PATCH 24/26] Exploded mines will push others aside. --- src/battle/mine.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/battle/mine.c b/src/battle/mine.c index 332e447..d3080fa 100644 --- a/src/battle/mine.c +++ b/src/battle/mine.c @@ -40,6 +40,7 @@ Entity *spawnMine(void) mine->type = ET_MINE; mine->health = mine->maxHealth = 1; + mine->speed = 1; mine->systemPower = SYSTEM_POWER; mine->texture = mineNormal; mine->action = think; @@ -62,6 +63,9 @@ static void think(void) self->angle -= 360; } + self->dx *= 0.99; + self->dy *= 0.99; + lookForFighters(); if (self->systemPower < SYSTEM_POWER && battle.stats[STAT_TIME] % 8 < 4) @@ -119,7 +123,7 @@ static void doSplashDamage(void) for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i]) { - if (e->health > 0 && e->type == ET_FIGHTER && !(e->flags & EF_IMMORTAL)) + if (e->health > 0 && (e->type == ET_FIGHTER || e->type == ET_MINE) && !(e->flags & EF_IMMORTAL)) { dist = getDistance(self->x, self->y, e->x, e->y); @@ -132,7 +136,18 @@ static void doSplashDamage(void) damage = 100; damage *= percent; - damageFighter(e, damage, 0); + if (e->type == ET_FIGHTER) + { + damageFighter(e, damage, 0); + } + else if (e->type == ET_MINE) + { + e->dx = e->x - self->x; + e->dy = e->y - self->y; + + e->dx *= 0.01; + e->dy *= 0.01; + } } } } From d329fbaf2f6a3c413c6d76c07b5fa75bedd2aeb4 Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 17:02:56 +0100 Subject: [PATCH 25/26] Only deploy mines if you're moving. --- src/battle/ai.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/battle/ai.c b/src/battle/ai.c index 5416d84..1f392ab 100644 --- a/src/battle/ai.c +++ b/src/battle/ai.c @@ -628,14 +628,18 @@ static void deployMine(void) { Entity *mine; - if (!self->reload) + if (!self->reload && self->thrust > 0) { mine = spawnMine(); mine->x = self->x; mine->y = self->y; + mine->dx = rand() % 20 - rand() % 20; + mine->dx *= 0.1; + mine->dy = rand() % 20 - rand() % 20; + mine->dy *= 0.1; mine->side = self->side; - self->reload = FPS + (FPS * (rand() % 5)); + self->reload = rand() % (FPS * 3); } } From 86b1f27f00a52d2ee9f96977b5aa42aee7291658 Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 1 Apr 2016 17:03:11 +0100 Subject: [PATCH 26/26] Misc misson tweaks. --- data/missions/aster/02 - return to aster #2.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/data/missions/aster/02 - return to aster #2.json b/data/missions/aster/02 - return to aster #2.json index 8389017..165bc57 100644 --- a/data/missions/aster/02 - return to aster #2.json +++ b/data/missions/aster/02 - return to aster #2.json @@ -5,6 +5,7 @@ "background" : "gfx/backgrounds/background04.jpg", "planet" : "gfx/planets/bluePlanet.png", "music" : "music/battle/track-3.mp3", + "manualComplete" : 1, "objectives" : [ { "description" : "Destroy all enemy forces", @@ -39,7 +40,7 @@ "number" : 5, "scatter" : 4000, "flags" : "+EF_AI_LEADER", - "aiFlags" : "+AIF_DROPS_MINES" + "aiFlags" : "+AIF_DROPS_MINES+AIF_WANDERS" }, { "types" : "Shale", @@ -58,6 +59,16 @@ "MSG_BOX Pope;Watch out for those mines. They're on proximity triggers and have a large area of effect.", "MSG_BOX Pope;Take them out from a distance, otherwise you'll be in trouble." ] + }, + { + "function" : "ALL_OBJECTIVES_COMPLETE", + "lines" : [ + "WAIT 1", + "MSG_BOX Pope;That's the bombers taken care of, but the area is still littered with mines.", + "MSG_BOX Pope;We'll need to get a team in here to take care of them.", + "WAIT_MSG_BOX", + "COMPLETE_MISSION" + ] } ] }