Skip to content

Commit

Permalink
Added commander shields
Browse files Browse the repository at this point in the history
  • Loading branch information
Monsterovich committed Oct 26, 2024
1 parent 2a9934f commit be7bb28
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 1 deletion.
3 changes: 2 additions & 1 deletion data/base/audio/audio.json
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,8 @@
{ "fileName": "scream.ogg", "loop": false, "range": 1800, "volume": 100 },
{ "fileName": "scream2.ogg", "loop": false, "range": 1800, "volume": 100 },
{ "fileName": "scream3.ogg", "loop": false, "range": 1800, "volume": 100 },
{ "fileName": "silence.ogg", "loop": false, "range": 1800, "volume": 100 }
{ "fileName": "silence.ogg", "loop": false, "range": 1800, "volume": 100 },
{ "fileName": "shield-hit.ogg", "loop": false, "range": 1800, "volume": 100 }
]
},
"Extra": {
Expand Down
Binary file added data/base/audio/sfx/misc/shield-hit.ogg
Binary file not shown.
1 change: 1 addition & 0 deletions data/base/wrf/audio.wrf
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ file WAV "scream.ogg"
file WAV "scream2.ogg"
file WAV "scream3.ogg"
file WAV "silence.ogg"
file WAV "shield-hit.ogg"
directory "audio/extra"
file WAV "lndgzne.ogg"
file WAV "nmedeted.ogg"
Expand Down
1 change: 1 addition & 0 deletions lib/sound/audio_id.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ static AUDIO_ID_MAP asAudioID[] =
{ID_SOUND_BARB_SCREAM2, "scream2.ogg"},
{ID_SOUND_BARB_SCREAM3, "scream3.ogg"},
{ID_SOUND_OF_SILENCE, "silence.ogg"},
{ID_SOUND_SHIELD_HIT, "shield-hit.ogg"},

/* Extra */
{ID_SOUND_LANDING_ZONE, "lndgzne.ogg"},
Expand Down
1 change: 1 addition & 0 deletions lib/sound/audio_id.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ enum INGAME_AUDIO
ID_SOUND_BARB_SCREAM2,
ID_SOUND_BARB_SCREAM3,
ID_SOUND_OF_SILENCE,
ID_SOUND_SHIELD_HIT,

/* Extra */

Expand Down
41 changes: 41 additions & 0 deletions src/combat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
#include "lib/framework/fixedpoint.h"
#include "lib/netplay/sync_debug.h"

#include "lib/ivis_opengl/ivisdef.h"

#include "lib/sound/audio.h"
#include "lib/sound/audio_id.h"

#include "action.h"
#include "combat.h"
#include "difficulty.h"
Expand All @@ -38,6 +43,12 @@
#include "qtscript.h"
#include "order.h"
#include "objmem.h"
#include "effects.h"



#define DROID_SHIELD_DAMAGE_SPREAD (16 - rand()%32)
#define DROID_SHIELD_PARTICLES (6 + rand()%8)

/* Fire a weapon at something */
bool combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, int weapon_slot)
Expand Down Expand Up @@ -485,6 +496,36 @@ int32_t objDamage(BASE_OBJECT *psObj, unsigned damage, unsigned originalhp, WEAP
return -(int64_t)65536 * psObj->body / originalhp;
}

// Drain shields first
if (psObj->type == OBJ_DROID) {
DROID *psDroid = castDroid(psObj);

if (psDroid->shieldPoints > 0) {
if (psDroid->shieldPoints > actualDamage) {
psDroid->shieldPoints -= actualDamage;
actualDamage = 0;
} else {
actualDamage -= psDroid->shieldPoints;
psDroid->shieldPoints = 0;
// shields are interrupted, wait for a while until regeneration starts again
psDroid->shieldInterruptRegenTime = psDroid->time;
psDroid->shieldRegenTime = psDroid->time;
}

Vector3i dv;
dv.y = psDroid->pos.z;
dv.y += (psDroid->sDisplay.imd->max.y * 2);

for (uint32_t i = 0; i < DROID_SHIELD_PARTICLES; i++) {
dv.x = psDroid->pos.x + DROID_SHIELD_DAMAGE_SPREAD;
dv.z = psDroid->pos.y + DROID_SHIELD_DAMAGE_SPREAD;
addEffect(&dv, EFFECT_FIREWORK, FIREWORK_TYPE_STARBURST, false, nullptr, 0, gameTime - deltaGameTime + 1);
}

audio_PlayStaticTrack(psDroid->pos.x, psDroid->pos.y, ID_SOUND_SHIELD_HIT);
}
}

// Subtract the dealt damage from the droid's remaining body points
psObj->body -= actualDamage;

Expand Down
9 changes: 9 additions & 0 deletions src/display3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3424,6 +3424,14 @@ bool eitherSelected(DROID *psDroid)
static void queueDroidPowerBarsRects(DROID *psDroid, bool drawBox, BatchedMultiRectRenderer& batchedMultiRectRenderer, size_t rectGroup)
{
UDWORD damage = PERCENT(psDroid->body, psDroid->originalBody);
UDWORD shields = 0;

if (psDroid->shieldPoints >= 0) {
int maxShieldPoints = droidGetMaxShieldPoints(psDroid);
shields = PERCENT(psDroid->shieldPoints, maxShieldPoints);
shields = static_cast<UDWORD>((float)psDroid->shieldPoints / (float)maxShieldPoints * (float)psDroid->sDisplay.screenR);
shields *= 2;
}

PIELIGHT powerCol = WZCOL_BLACK;
PIELIGHT powerColShadow = WZCOL_BLACK;
Expand Down Expand Up @@ -3464,6 +3472,7 @@ static void queueDroidPowerBarsRects(DROID *psDroid, bool drawBox, BatchedMultiR
batchedMultiRectRenderer.addRect(PIERECT_DrawRequest(psDroid->sDisplay.screenX - psDroid->sDisplay.screenR - 1, psDroid->sDisplay.screenY + psDroid->sDisplay.screenR + 2, psDroid->sDisplay.screenX + psDroid->sDisplay.screenR + 1, psDroid->sDisplay.screenY + psDroid->sDisplay.screenR + 6, WZCOL_RELOAD_BACKGROUND), rectGroup);
batchedMultiRectRenderer.addRect(PIERECT_DrawRequest(psDroid->sDisplay.screenX - psDroid->sDisplay.screenR, psDroid->sDisplay.screenY + psDroid->sDisplay.screenR + 3, psDroid->sDisplay.screenX - psDroid->sDisplay.screenR + damage, psDroid->sDisplay.screenY + psDroid->sDisplay.screenR + 4, powerCol), rectGroup);
batchedMultiRectRenderer.addRect(PIERECT_DrawRequest(psDroid->sDisplay.screenX - psDroid->sDisplay.screenR, psDroid->sDisplay.screenY + psDroid->sDisplay.screenR + 4, psDroid->sDisplay.screenX - psDroid->sDisplay.screenR + damage, psDroid->sDisplay.screenY + psDroid->sDisplay.screenR + 5, powerColShadow), rectGroup);
batchedMultiRectRenderer.addRect(PIERECT_DrawRequest(psDroid->sDisplay.screenX - psDroid->sDisplay.screenR, psDroid->sDisplay.screenY + psDroid->sDisplay.screenR + 8, psDroid->sDisplay.screenX - psDroid->sDisplay.screenR + shields, psDroid->sDisplay.screenY + psDroid->sDisplay.screenR + 6, WZCOL_LBLUE), rectGroup);
}

static void queueDroidEnemyHealthBarsRects(DROID *psDroid, BatchedMultiRectRenderer& batchedMultiRectRenderer, size_t rectGroup)
Expand Down
42 changes: 42 additions & 0 deletions src/droid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,9 @@ void droidUpdate(DROID *psDroid)
droidUpdateDroidSelfRepair(psDroid);
}

if (bMultiPlayer) {
droidUpdateShields(psDroid);
}

/* Update the fire damage data */
if (psDroid->periodicalDamageStart != 0 && psDroid->periodicalDamageStart != gameTime - deltaGameTime) // -deltaGameTime, since projectiles are updated after droids.
Expand Down Expand Up @@ -953,6 +956,44 @@ void droidUpdate(DROID *psDroid)
CHECK_DROID(psDroid);
}

void droidUpdateShields(DROID *psDroid) {
if (hasCommander(psDroid) || psDroid->droidType == DROID_COMMAND) {
if (psDroid->shieldPoints < 0) {
psDroid->shieldPoints = 0;
psDroid->shieldRegenTime = gameTime;
psDroid->shieldInterruptRegenTime = gameTime;

} else {
if (gameTime - psDroid->shieldInterruptRegenTime >= droidCalculateShieldInterruptRegenTime(psDroid)) {
if (gameTime - psDroid->shieldRegenTime >= droidCalculateShieldRegenTime(psDroid)) {
for (uint32_t i = 0; i < 4; i++) {
if (psDroid->shieldPoints < droidGetMaxShieldPoints(psDroid)) {
psDroid->shieldPoints += 1;
}
}
psDroid->shieldRegenTime = gameTime;
}
}
}
} else {
// unit has lost commander, shields are down!
psDroid->shieldPoints = -1;
}
}

uint32_t droidCalculateShieldRegenTime(DROID *psDroid) {
return DROID_INITIAL_SHIELD_REGEN_TIME - (DROID_SHIELD_REGEN_TIME_DEC * getDroidLevel(psDroid));
}

uint32_t droidCalculateShieldInterruptRegenTime(DROID *psDroid) {
return DROID_INITIAL_SHIELD_INTERRUPT_REGEN_TIME - (DROID_SHIELD_INTERRUPT_REGEN_TIME_DEC * getDroidLevel(psDroid));
}

int32_t droidGetMaxShieldPoints(DROID *psDroid) {
double percent = static_cast<double>(psDroid->originalBody) / 100.0f;
return std::round(percent * (DROID_INITIAL_SHILED_POINTS_PERCENT + DROID_ADDITVE_SHILED_POINTS_PERCENT * getDroidLevel(psDroid)));

Check warning on line 994 in src/droid.cpp

View workflow job for this annotation

GitHub Actions / Fedora :LATEST [GCC]

conversion from 'double' to 'int32_t' {aka 'int'} may change value [-Wfloat-conversion]

Check warning on line 994 in src/droid.cpp

View workflow job for this annotation

GitHub Actions / Arch :LATEST [GCC]

conversion from ‘double’ to ‘int32_t’ {aka ‘int’} may change value [-Wfloat-conversion]

Check warning on line 994 in src/droid.cpp

View workflow job for this annotation

GitHub Actions / Fedora :LATEST [GCC -m32]

conversion from 'double' to 'int32_t' {aka 'int'} may change value [-Wfloat-conversion]

Check warning on line 994 in src/droid.cpp

View workflow job for this annotation

GitHub Actions / Arch :LATEST [Clang]

implicit conversion turns floating-point number into integer: 'double' to 'int32_t' (aka 'int') [-Wfloat-conversion]

Check warning on line 994 in src/droid.cpp

View workflow job for this annotation

GitHub Actions / Ubuntu 22.04 [Clang]

implicit conversion turns floating-point number into integer: 'double' to 'int32_t' (aka 'int') [-Wfloat-conversion]

Check warning on line 994 in src/droid.cpp

View workflow job for this annotation

GitHub Actions / Ubuntu 24.04 [Clang]

implicit conversion turns floating-point number into integer: 'double' to 'int32_t' (aka 'int') [-Wfloat-conversion]
}

/* See if a droid is next to a structure */
static bool droidNextToStruct(DROID *psDroid, STRUCTURE *psStruct)
{
Expand Down Expand Up @@ -1723,6 +1764,7 @@ DROID *reallyBuildDroid(const DROID_TEMPLATE *pTemplate, Position pos, UDWORD pl
droid.experience = 0;
}
droid.kills = 0;
droid.shieldPoints = -1;

droidSetBits(pTemplate, &droid);

Expand Down
12 changes: 12 additions & 0 deletions src/droid.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,18 @@ int32_t droidDamage(DROID *psDroid, unsigned damage, WEAPON_CLASS weaponClass, W
/* The main update routine for all droids */
void droidUpdate(DROID *psDroid);

/* Update droid shields. */
void droidUpdateShields(DROID *psDroid);

/* Calculate the droid's shield regeneration step time */
uint32_t droidCalculateShieldRegenTime(DROID *psDroid);

/* Calculate the droid's shield interruption time */
uint32_t droidCalculateShieldInterruptRegenTime(DROID *psDroid);

/* Get droid maximum shield points */
int32_t droidGetMaxShieldPoints(DROID *psDroid);

/* Set up a droid to build a structure - returns true if successful */
enum DroidStartBuild {DroidStartBuildFailed, DroidStartBuildSuccess, DroidStartBuildPending};
DroidStartBuild droidStartBuild(DROID *psDroid);
Expand Down
10 changes: 10 additions & 0 deletions src/droiddef.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@
//defines how many times to perform the iteration on looking for a blank location
#define LOOK_FOR_EMPTY_TILE 20

#define DROID_INITIAL_SHILED_POINTS_PERCENT 5.0f
#define DROID_ADDITVE_SHILED_POINTS_PERCENT 2.5f
#define DROID_INITIAL_SHIELD_REGEN_TIME 32
#define DROID_SHIELD_REGEN_TIME_DEC 2
#define DROID_INITIAL_SHIELD_INTERRUPT_REGEN_TIME 2000
#define DROID_SHIELD_INTERRUPT_REGEN_TIME_DEC 100

typedef std::vector<DROID_ORDER_DATA> OrderList;

struct DROID_TEMPLATE : public BASE_STATS
Expand Down Expand Up @@ -150,6 +157,9 @@ struct DROID : public BASE_OBJECT
UDWORD baseSpeed; ///< the base speed dependent on propulsion type
UDWORD originalBody; ///< the original body points
uint32_t experience;
int32_t shieldPoints;
UDWORD shieldRegenTime;
UDWORD shieldInterruptRegenTime;
uint32_t kills;
UDWORD lastFrustratedTime; ///< Set when eg being stuck; used for eg firing indiscriminately at map features to clear the way
SWORD resistance; ///< used in Electronic Warfare
Expand Down

0 comments on commit be7bb28

Please sign in to comment.