From cb9504c9aba3d42464541f684495dab3a70a4a97 Mon Sep 17 00:00:00 2001 From: Cyp Date: Wed, 28 Dec 2011 14:42:41 +0100 Subject: [PATCH] Render droid until the exact time the projectile hits and render explosion effects at that time. Or in the case of multiple projectiles hitting, render until the last projectile in the projectile list hits (which might not have been the impact with the latest gameTime). --- src/action.cpp | 2 +- src/component.cpp | 4 ++-- src/component.h | 2 +- src/display3d.cpp | 42 +++++++++++++++++++++++------------------- src/droid.cpp | 20 ++++++++++---------- src/droid.h | 4 ++-- src/feature.cpp | 16 ++++++++-------- src/feature.h | 4 ++-- src/move.cpp | 4 ++-- src/multibot.cpp | 2 +- src/multijoin.cpp | 4 ++-- src/multistruct.cpp | 2 +- src/objmem.cpp | 4 ++-- src/order.cpp | 2 +- src/projectile.cpp | 20 ++++++++++---------- src/scriptfuncs.cpp | 2 +- src/structure.cpp | 25 +++++++++++++------------ src/structure.h | 4 ++-- 18 files changed, 84 insertions(+), 79 deletions(-) diff --git a/src/action.cpp b/src/action.cpp index 4219772ef3f..dd183f7175f 100644 --- a/src/action.cpp +++ b/src/action.cpp @@ -1942,7 +1942,7 @@ void actionUpdateDroid(DROID *psDroid) else { debug(LOG_DEATH, "Droid %d destructed", (int)psDroid->id); - destroyDroid(psDroid); + destroyDroid(psDroid, psDroid->actionStarted + ACTION_DESTRUCT_TIME); } } break; diff --git a/src/component.cpp b/src/component.cpp index c0170149294..988688b5c8b 100644 --- a/src/component.cpp +++ b/src/component.cpp @@ -1052,7 +1052,7 @@ void displayComponentObject(DROID *psDroid) } -void destroyFXDroid(DROID *psDroid) +void destroyFXDroid(DROID *psDroid, unsigned impactTime) { for (int i = 0; i < 5; ++i) { @@ -1114,7 +1114,7 @@ void destroyFXDroid(DROID *psDroid) } // Tell the effect system that it needs to use this player's color for the next effect SetEffectForPlayer(psDroid->player); - addEffect(&pos, EFFECT_GRAVITON, GRAVITON_TYPE_EMITTING_DR, true, psImd, getPlayerColour(psDroid->player), gameTime - deltaGameTime); + addEffect(&pos, EFFECT_GRAVITON, GRAVITON_TYPE_EMITTING_DR, true, psImd, getPlayerColour(psDroid->player), impactTime); } } diff --git a/src/component.h b/src/component.h index 593591cbb5e..6ce1c491f09 100644 --- a/src/component.h +++ b/src/component.h @@ -66,7 +66,7 @@ void displayComponentObject(DROID *psDroid); void compPersonToBits(DROID *psDroid); SDWORD rescaleButtonObject(SDWORD radius, SDWORD baseScale,SDWORD baseRadius); -void destroyFXDroid(DROID *psDroid); +void destroyFXDroid(DROID *psDroid, unsigned impactTime); /* Pass in the stats you're interested in and the COMPONENT - double reference, but works. NOTE: Unused!*/ #define PART_IMD(STATS,DROID,COMPONENT,PLAYER) (STATS[DROID->asBits[COMPONENT].nStat].pIMD) diff --git a/src/display3d.cpp b/src/display3d.cpp index 8a9be46e1bf..0a6907b8ed7 100644 --- a/src/display3d.cpp +++ b/src/display3d.cpp @@ -1389,22 +1389,22 @@ void renderAnimComponent( const COMPONENT_OBJECT *psObj ) /// Draw the buildings void displayStaticObjects( void ) { - STRUCTURE *psStructure; - UDWORD clan; - UDWORD test = 0; ANIM_OBJECT *psAnimObj; // to solve the flickering edges of baseplates pie_SetDepthOffset(-1.0f); /* Go through all the players */ - for (clan = 0; clan < MAX_PLAYERS; clan++) + for (unsigned player = 0; player <= MAX_PLAYERS; ++player) { + BASE_OBJECT *list = player < MAX_PLAYERS? apsStructLists[player] : psDestroyedObj; + /* Now go all buildings for that player */ - for(psStructure = apsStructLists[clan]; psStructure != NULL; - psStructure = psStructure->psNext) + for (; list != NULL; list = list->psNext) + if (list->type == OBJ_STRUCTURE && (list->died == 0 || list->died > graphicsTime)) { - test++; + STRUCTURE *psStructure = castStructure(list); + /* Worth rendering the structure? */ if(clipXY(psStructure->pos.x,psStructure->pos.y)) { @@ -1659,22 +1659,24 @@ void displayDelivPoints(void) /// Draw the features void displayFeatures( void ) { - FEATURE *psFeature; - UDWORD clan; - - /* player can only be 0 for the features */ - clan = 0; + // player can only be 0 for the features. + for (unsigned player = 0; player <= 1; ++player) + { + BASE_OBJECT *list = player < 1? apsFeatureLists[player] : psDestroyedObj; /* Go through all the features */ - for(psFeature = apsFeatureLists[clan]; psFeature != NULL; - psFeature = psFeature->psNext) + for (; list != NULL; list = list->psNext) + if (list->type == OBJ_FEATURE && (list->died == 0 || list->died > graphicsTime)) { + FEATURE *psFeature = castFeature(list); + /* Is the feature worth rendering? */ if(clipXY(psFeature->pos.x,psFeature->pos.y)) { renderFeature(psFeature); } } + } } /// Draw the Proximity messages for the *SELECTED PLAYER ONLY* @@ -1760,16 +1762,18 @@ static void displayAnimation( ANIM_OBJECT * psAnimObj, bool bHoldOnFirstFrame ) /// Draw the droids void displayDynamicObjects( void ) { - DROID *psDroid; ANIM_OBJECT *psAnimObj; - UDWORD clan; /* Need to go through all the droid lists */ - for(clan = 0; clan < MAX_PLAYERS; clan++) + for (unsigned player = 0; player <= MAX_PLAYERS; ++player) { - for(psDroid = apsDroidLists[clan]; psDroid != NULL; - psDroid = psDroid->psNext) + BASE_OBJECT *list = player < MAX_PLAYERS? apsDroidLists[player] : psDestroyedObj; + + for (; list != NULL; list = list->psNext) + if (list->type == OBJ_DROID && (list->died == 0 || list->died > graphicsTime)) { + DROID *psDroid = castDroid(list); + /* Find out whether the droid is worth rendering */ if(clipXY(psDroid->pos.x,psDroid->pos.y)) { diff --git a/src/droid.cpp b/src/droid.cpp index 53038d2d1ba..775b8fd944a 100644 --- a/src/droid.cpp +++ b/src/droid.cpp @@ -151,7 +151,7 @@ bool droidInit(void) * * NOTE: This function will damage but _never_ destroy transports when in single player (campaign) mode */ -int32_t droidDamage(DROID *psDroid, uint32_t damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass) +int32_t droidDamage(DROID *psDroid, unsigned damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass, unsigned impactTime) { int32_t relativeDamage; @@ -224,12 +224,12 @@ int32_t droidDamage(DROID *psDroid, uint32_t damage, WEAPON_CLASS weaponClass, W if (bMultiPlayer && !bMultiMessages) { bMultiMessages = true; - destroyDroid(psDroid); + destroyDroid(psDroid, impactTime); bMultiMessages = false; } else { - destroyDroid(psDroid); + destroyDroid(psDroid, impactTime); } } } @@ -509,7 +509,7 @@ void removeDroidBase(DROID *psDel) killDroid(psDel); } -static void removeDroidFX(DROID *psDel) +static void removeDroidFX(DROID *psDel, unsigned impactTime) { Vector3i pos; @@ -537,16 +537,16 @@ static void removeDroidFX(DROID *psDel) } else if (psDel->visible[selectedPlayer]) { - destroyFXDroid(psDel); + destroyFXDroid(psDel, impactTime); pos.x = psDel->pos.x; pos.z = psDel->pos.y; pos.y = psDel->pos.z; - addEffect(&pos, EFFECT_DESTRUCTION, DESTRUCTION_TYPE_DROID, false, NULL, 0, gameTime - deltaGameTime); + addEffect(&pos, EFFECT_DESTRUCTION, DESTRUCTION_TYPE_DROID, false, NULL, 0, impactTime); audio_PlayStaticTrack( psDel->pos.x, psDel->pos.y, ID_SOUND_EXPLOSION ); } } -void destroyDroid(DROID *psDel) +void destroyDroid(DROID *psDel, unsigned impactTime) { if (psDel->lastHitWeapon == WSC_LAS_SAT) // darken tile if lassat. { @@ -568,8 +568,9 @@ void destroyDroid(DROID *psDel) } } - removeDroidFX(psDel); + removeDroidFX(psDel, impactTime); removeDroidBase(psDel); + psDel->died = impactTime; return; } @@ -865,8 +866,7 @@ void droidUpdate(DROID *psDroid) { psDroid->burnDamage += damageToDo; - //just assume the burn damage is from FRONT - droidDamage(psDroid, damageToDo, WC_HEAT, WSC_FLAME); + droidDamage(psDroid, damageToDo, WC_HEAT, WSC_FLAME, gameTime - deltaGameTime/2); } } } diff --git a/src/droid.h b/src/droid.h index 7f718500668..b825ebcd0fa 100644 --- a/src/droid.h +++ b/src/droid.h @@ -128,7 +128,7 @@ extern UDWORD calcTemplatePower(DROID_TEMPLATE *psTemplate); bool idfDroid(DROID *psDroid); /* Do damage to a droid */ -int32_t droidDamage(DROID *psDroid, uint32_t damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass); +int32_t droidDamage(DROID *psDroid, unsigned damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass, unsigned impactTime); /* The main update routine for all droids */ extern void droidUpdate(DROID *psDroid); @@ -173,7 +173,7 @@ extern bool droidUpdateRestore( DROID *psDroid ); extern void recycleDroid(DROID *psDel); /* Remove a droid and free it's memory */ -extern void destroyDroid(DROID *psDel); +void destroyDroid(DROID *psDel, unsigned impactTime); /* Same as destroy droid except no graphical effects */ extern void vanishDroid(DROID *psDel); diff --git a/src/feature.cpp b/src/feature.cpp index 31b4bd99285..5f3fe6306e4 100644 --- a/src/feature.cpp +++ b/src/feature.cpp @@ -165,7 +165,7 @@ void featureStatsShutDown(void) * \param weaponClass,weaponSubClass the class and subclass of the weapon that deals the damage * \return < 0 never, >= 0 always */ -int32_t featureDamage(FEATURE *psFeature, UDWORD damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass) +int32_t featureDamage(FEATURE *psFeature, unsigned damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass, unsigned impactTime) { int32_t relativeDamage; @@ -180,7 +180,7 @@ int32_t featureDamage(FEATURE *psFeature, UDWORD damage, WEAPON_CLASS weaponClas if (relativeDamage < 0) { debug(LOG_ATTACK, "feature (id %d) DESTROYED", psFeature->id); - destroyFeature(psFeature); + destroyFeature(psFeature, impactTime); return relativeDamage * -1; } else @@ -365,10 +365,9 @@ bool removeFeature(FEATURE *psDel) ASSERT_OR_RETURN(false, psDel != NULL, "Invalid feature pointer"); ASSERT_OR_RETURN(false, !psDel->died, "Feature already dead"); - if(bMultiMessages && !ingame.localJoiningInProgress) + if (bMultiMessages && !ingame.localJoiningInProgress && !isInSync()) { SendDestroyFeature(psDel); // inform other players of destruction - return true; // Wait for our message before really destroying the feature. } //remove from the map data @@ -423,7 +422,7 @@ bool removeFeature(FEATURE *psDel) } /* Remove a Feature and free it's memory */ -bool destroyFeature(FEATURE *psDel) +bool destroyFeature(FEATURE *psDel, unsigned impactTime) { UDWORD widthScatter,breadthScatter,heightScatter, i; EFFECT_TYPE explosionSize; @@ -457,7 +456,7 @@ bool destroyFeature(FEATURE *psDel) pos.x = psDel->pos.x + widthScatter - rand()%(2*widthScatter); pos.z = psDel->pos.y + breadthScatter - rand()%(2*breadthScatter); pos.y = psDel->pos.z + 32 + rand()%heightScatter; - addEffect(&pos, EFFECT_EXPLOSION, explosionSize, false, NULL, 0, gameTime - deltaGameTime); + addEffect(&pos, EFFECT_EXPLOSION, explosionSize, false, NULL, 0, impactTime); } if(psDel->psStats->subType == FEAT_SKYSCRAPER) @@ -465,7 +464,7 @@ bool destroyFeature(FEATURE *psDel) pos.x = psDel->pos.x; pos.z = psDel->pos.y; pos.y = psDel->pos.z; - addEffect(&pos, EFFECT_DESTRUCTION, DESTRUCTION_TYPE_SKYSCRAPER, true, psDel->sDisplay.imd, 0, gameTime - deltaGameTime); + addEffect(&pos, EFFECT_DESTRUCTION, DESTRUCTION_TYPE_SKYSCRAPER, true, psDel->sDisplay.imd, 0, impactTime); initPerimeterSmoke(psDel->sDisplay.imd, pos); shakeStart(); @@ -475,7 +474,7 @@ bool destroyFeature(FEATURE *psDel) pos.x = psDel->pos.x; pos.z = psDel->pos.y; pos.y = map_Height(pos.x,pos.z); - addEffect(&pos, EFFECT_DESTRUCTION, DESTRUCTION_TYPE_FEATURE, false, NULL, 0, gameTime - deltaGameTime); + addEffect(&pos, EFFECT_DESTRUCTION, DESTRUCTION_TYPE_FEATURE, false, NULL, 0, impactTime); //play sound // ffs gj @@ -520,6 +519,7 @@ bool destroyFeature(FEATURE *psDel) } removeFeature(psDel); + psDel->died = impactTime; return true; } diff --git a/src/feature.h b/src/feature.h index d4a62dca52d..e6db24d318a 100644 --- a/src/feature.h +++ b/src/feature.h @@ -49,12 +49,12 @@ extern void featureUpdate(FEATURE *psFeat); extern bool removeFeature(FEATURE *psDel); /* Remove a Feature and free it's memory */ -extern bool destroyFeature(FEATURE *psDel); +bool destroyFeature(FEATURE *psDel, unsigned impactTime); /* get a feature stat id from its name */ extern SDWORD getFeatureStatFromName(const char *pName); -int32_t featureDamage(FEATURE *psFeature, UDWORD damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass); +int32_t featureDamage(FEATURE *psFeature, unsigned damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass, unsigned impactTime); extern void featureInitVars(void); diff --git a/src/move.cpp b/src/move.cpp index f914bd0c1c3..0ce80904b34 100644 --- a/src/move.cpp +++ b/src/move.cpp @@ -732,7 +732,7 @@ static void moveCheckSquished(DROID *psDroid, int32_t emx, int32_t emy) if ((psDroid->player != psObj->player) && !aiCheckAlliances(psDroid->player, psObj->player)) { // run over a bloke - kill him - destroyDroid((DROID *)psObj); + destroyDroid((DROID *)psObj, gameTime); scoreUpdateVar(WD_BARBARIANS_MOWED_DOWN); } } @@ -1630,7 +1630,7 @@ static void moveUpdateDroidPos(DROID *psDroid, int32_t dx, int32_t dy) if (psDroid->droidType != DROID_TRANSPORTER) { /* dreadful last-ditch crash-avoiding hack - sort this! - GJ */ - destroyDroid( psDroid ); + destroyDroid(psDroid, gameTime); return; } } diff --git a/src/multibot.cpp b/src/multibot.cpp index e54cb139f8b..8aefcb424f0 100644 --- a/src/multibot.cpp +++ b/src/multibot.cpp @@ -804,7 +804,7 @@ bool recvDestroyDroid(NETQUEUE queue) { turnOffMultiMsg(true); debug(LOG_DEATH, "Killing droid %d on request from player %d - huh?", psDroid->id, queue.index); - destroyDroid(psDroid); + destroyDroid(psDroid, gameTime); turnOffMultiMsg(false); } else diff --git a/src/multijoin.cpp b/src/multijoin.cpp index 6cd26d621ef..a1c3fcdbb01 100644 --- a/src/multijoin.cpp +++ b/src/multijoin.cpp @@ -144,7 +144,7 @@ void clearPlayer(UDWORD player,bool quietly) } else // show effects { - destroyDroid(apsDroidLists[player]); + destroyDroid(apsDroidLists[player], gameTime); } } @@ -161,7 +161,7 @@ void clearPlayer(UDWORD player,bool quietly) } else // show effects { - destroyStruct(psStruct); + destroyStruct(psStruct, gameTime); } psStruct = psNext; diff --git a/src/multistruct.cpp b/src/multistruct.cpp index 8ba3790963d..8d98c4c2094 100644 --- a/src/multistruct.cpp +++ b/src/multistruct.cpp @@ -226,7 +226,7 @@ bool recvDestroyStructure(NETQUEUE queue) { turnOffMultiMsg(true); // Remove the struct from remote players machine - destroyStruct(psStruct); + destroyStruct(psStruct, gameTime); turnOffMultiMsg(false); // NOTE: I do not think this should be here! technologyGiveAway(psStruct); diff --git a/src/objmem.cpp b/src/objmem.cpp index e93025d9b23..c549f918997 100644 --- a/src/objmem.cpp +++ b/src/objmem.cpp @@ -143,7 +143,7 @@ void objmemUpdate(void) were destroyed before this turn */ /* First remove the objects from the start of the list */ - while (psDestroyedObj != NULL && psDestroyedObj->died != gameTime) + while (psDestroyedObj != NULL && psDestroyedObj->died < gameTime - deltaGameTime) { psNext = psDestroyedObj->psNext; objmemDestroy(psDestroyedObj); @@ -155,7 +155,7 @@ void objmemUpdate(void) for(psCurr = psPrev = psDestroyedObj; psCurr != NULL; psCurr = psNext) { psNext = psCurr->psNext; - if (psCurr->died != gameTime) + if (psCurr->died < gameTime - deltaGameTime) { objmemDestroy(psCurr); diff --git a/src/order.cpp b/src/order.cpp index c5474a797ca..0a0496edea5 100644 --- a/src/order.cpp +++ b/src/order.cpp @@ -943,7 +943,7 @@ void orderUpdateDroid(DROID *psDroid) if (psDroid->actionStarted + RUN_BURN_TIME < gameTime) { debug(LOG_DEATH, "orderUpdateDroid: Droid %d burned to death", psDroid->id); // why is this an order? - destroyDroid( psDroid ); + destroyDroid(psDroid, psDroid->actionStarted + RUN_BURN_TIME); } break; case DORDER_RUN: diff --git a/src/projectile.cpp b/src/projectile.cpp index a4a64259c6c..03ade5483cc 100644 --- a/src/projectile.cpp +++ b/src/projectile.cpp @@ -110,7 +110,7 @@ static void proj_ImpactFunc( PROJECTILE *psObj ); static void proj_PostImpactFunc( PROJECTILE *psObj ); static void proj_checkBurnDamage( BASE_OBJECT *apsList, PROJECTILE *psProj); -static int32_t objectDamage(BASE_OBJECT *psObj, UDWORD damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass); +static int32_t objectDamage(BASE_OBJECT *psObj, unsigned damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass, unsigned impactTime); static inline void setProjectileDestination(PROJECTILE *psProj, BASE_OBJECT *psObj) @@ -1147,7 +1147,7 @@ static void proj_ImpactFunc( PROJECTILE *psObj ) psObj->psDest->id, psObj->psDest->player); // Damage the object - relativeDamage = objectDamage(psObj->psDest, damage, psStats->weaponClass,psStats->weaponSubClass); + relativeDamage = objectDamage(psObj->psDest, damage, psStats->weaponClass, psStats->weaponSubClass, psObj->time); proj_UpdateKills(psObj, relativeDamage); @@ -1218,7 +1218,7 @@ static void proj_ImpactFunc( PROJECTILE *psObj ) turnOffMultiMsg(true); } - relativeDamage = droidDamage(psCurrD, damage, psStats->weaponClass, psStats->weaponSubClass); + relativeDamage = droidDamage(psCurrD, damage, psStats->weaponClass, psStats->weaponSubClass, psObj->time); turnOffMultiMsg(false); // multiplay msgs back on. @@ -1257,7 +1257,7 @@ static void proj_ImpactFunc( PROJECTILE *psObj ) } } - relativeDamage = structureDamage(psCurrS, damage, psStats->weaponClass, psStats->weaponSubClass); + relativeDamage = structureDamage(psCurrS, damage, psStats->weaponClass, psStats->weaponSubClass, psObj->time); proj_UpdateKills(psObj, relativeDamage); } } @@ -1293,7 +1293,7 @@ static void proj_ImpactFunc( PROJECTILE *psObj ) psStats->weaponEffect, (BASE_OBJECT *)psCurrF), psStats->weaponClass, - psStats->weaponSubClass); + psStats->weaponSubClass, psObj->time); proj_UpdateKills(psObj, relativeDamage); } } @@ -1488,7 +1488,7 @@ static void proj_checkBurnDamage( BASE_OBJECT *apsList, PROJECTILE *psProj) debug(LOG_NEVER, "Burn damage of %d to object %d, player %d\n", damageToDo, psCurr->id, psCurr->player); - relativeDamage = objectDamage(psCurr, damageToDo, psStats->weaponClass,psStats->weaponSubClass); + relativeDamage = objectDamage(psCurr, damageToDo, psStats->weaponClass, psStats->weaponSubClass, gameTime - deltaGameTime/2); psCurr->burnDamage += damageToDo; proj_UpdateKills(psProj, relativeDamage); } @@ -1628,20 +1628,20 @@ UDWORD calcDamage(UDWORD baseDamage, WEAPON_EFFECT weaponEffect, BASE_OBJECT *ps * multiplied by -1, resulting in a negative number. Killed features do not * result in negative numbers. */ -static int32_t objectDamage(BASE_OBJECT *psObj, UDWORD damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass) +static int32_t objectDamage(BASE_OBJECT *psObj, unsigned damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass, unsigned impactTime) { switch (psObj->type) { case OBJ_DROID: - return droidDamage((DROID *)psObj, damage, weaponClass,weaponSubClass); + return droidDamage((DROID *)psObj, damage, weaponClass, weaponSubClass, impactTime); break; case OBJ_STRUCTURE: - return structureDamage((STRUCTURE *)psObj, damage, weaponClass, weaponSubClass); + return structureDamage((STRUCTURE *)psObj, damage, weaponClass, weaponSubClass, impactTime); break; case OBJ_FEATURE: - return featureDamage((FEATURE *)psObj, damage, weaponClass, weaponSubClass); + return featureDamage((FEATURE *)psObj, damage, weaponClass, weaponSubClass, impactTime); break; case OBJ_PROJECTILE: diff --git a/src/scriptfuncs.cpp b/src/scriptfuncs.cpp index d719f3734a0..4f19c0c3e3c 100644 --- a/src/scriptfuncs.cpp +++ b/src/scriptfuncs.cpp @@ -4844,7 +4844,7 @@ SDWORD sX,sY; { if(bVisible) { - destroyFeature(psFeature); + destroyFeature(psFeature, gameTime); } else { diff --git a/src/structure.cpp b/src/structure.cpp index 83d08027594..444364c7bed 100644 --- a/src/structure.cpp +++ b/src/structure.cpp @@ -720,7 +720,7 @@ void handleAbandonedStructures() * \param weaponSubClass the subclass of the weapon that deals the damage * \return < 0 when the dealt damage destroys the structure, > 0 when the structure survives */ -int32_t structureDamage(STRUCTURE *psStructure, UDWORD damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass) +int32_t structureDamage(STRUCTURE *psStructure, unsigned damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass, unsigned impactTime) { int32_t relativeDamage; @@ -735,7 +735,7 @@ int32_t structureDamage(STRUCTURE *psStructure, UDWORD damage, WEAPON_CLASS weap if (relativeDamage < 0) { debug(LOG_ATTACK, "Structure (id %d) DESTROYED", psStructure->id); - destroyStruct(psStructure); + destroyStruct(psStructure, impactTime); } else { @@ -4588,7 +4588,7 @@ bool removeStruct(STRUCTURE *psDel, bool bDestroy) } /* Remove a structure */ -bool destroyStruct(STRUCTURE *psDel) +bool destroyStruct(STRUCTURE *psDel, unsigned impactTime) { UDWORD widthScatter,breadthScatter,heightScatter; bool resourceFound = false; @@ -4600,7 +4600,7 @@ bool destroyStruct(STRUCTURE *psDel) CHECK_STRUCTURE(psDel); - if (bMultiMessages) + if (bMultiMessages && !isInSync()) { // Every player should be sending this message at once, and ignoring it later. SendDestroyStructure(psDel); @@ -4625,7 +4625,7 @@ bool destroyStruct(STRUCTURE *psDel) pos.x = psDel->pos.x + widthScatter - rand()%(2*widthScatter); pos.z = psDel->pos.y + breadthScatter - rand()%(2*breadthScatter); pos.y = psDel->pos.z + 32 + rand()%heightScatter; - addEffect(&pos, EFFECT_EXPLOSION, EXPLOSION_TYPE_MEDIUM, false, NULL, 0, gameTime - deltaGameTime); + addEffect(&pos, EFFECT_EXPLOSION, EXPLOSION_TYPE_MEDIUM, false, NULL, 0, impactTime); } /* Get coordinates for everybody! */ @@ -4647,36 +4647,36 @@ bool destroyStruct(STRUCTURE *psDel) /* Give a duration */ effectGiveAuxVarSec(burnDurationWall); /* Normal fire - no smoke */ - addEffect(&pos, EFFECT_FIRE, FIRE_TYPE_LOCALISED, false, NULL, 0, gameTime - deltaGameTime); + addEffect(&pos, EFFECT_FIRE, FIRE_TYPE_LOCALISED, false, NULL, 0, impactTime); } else if(psDel->pStructureType->type == REF_RESOURCE_EXTRACTOR) // oil resources { /* Oil resources burn AND puff out smoke AND for longer*/ effectGiveAuxVarSec(burnDurationOilWell); - addEffect(&pos, EFFECT_FIRE, FIRE_TYPE_SMOKY, false, NULL, 0, gameTime - deltaGameTime); + addEffect(&pos, EFFECT_FIRE, FIRE_TYPE_SMOKY, false, NULL, 0, impactTime); } else // everything else { /* Give a duration */ effectGiveAuxVarSec(burnDurationOther); - addEffect(&pos, EFFECT_FIRE, FIRE_TYPE_LOCALISED, false, NULL, 0, gameTime - deltaGameTime); + addEffect(&pos, EFFECT_FIRE, FIRE_TYPE_LOCALISED, false, NULL, 0, impactTime); } /* Power stations have their own desctruction sequence */ if(psDel->pStructureType->type == REF_POWER_GEN) { - addEffect(&pos, EFFECT_DESTRUCTION, DESTRUCTION_TYPE_POWER_STATION, false, NULL, 0, gameTime - deltaGameTime); + addEffect(&pos, EFFECT_DESTRUCTION, DESTRUCTION_TYPE_POWER_STATION, false, NULL, 0, impactTime); pos.y += SHOCK_WAVE_HEIGHT; - addEffect(&pos, EFFECT_EXPLOSION, EXPLOSION_TYPE_SHOCKWAVE, false, NULL, 0, gameTime - deltaGameTime); + addEffect(&pos, EFFECT_EXPLOSION, EXPLOSION_TYPE_SHOCKWAVE, false, NULL, 0, impactTime); } /* As do wall sections */ else if(bMinor) { - addEffect(&pos, EFFECT_DESTRUCTION, DESTRUCTION_TYPE_WALL_SECTION, false, NULL, 0, gameTime - deltaGameTime); + addEffect(&pos, EFFECT_DESTRUCTION, DESTRUCTION_TYPE_WALL_SECTION, false, NULL, 0, impactTime); } else // and everything else goes here..... { - addEffect(&pos, EFFECT_DESTRUCTION, DESTRUCTION_TYPE_STRUCTURE, false, NULL, 0, gameTime - deltaGameTime); + addEffect(&pos, EFFECT_DESTRUCTION, DESTRUCTION_TYPE_STRUCTURE, false, NULL, 0, impactTime); } /* shake the screen if we're near enough */ @@ -4705,6 +4705,7 @@ bool destroyStruct(STRUCTURE *psDel) } resourceFound = removeStruct(psDel, true); + psDel->died = impactTime; // Leave burn marks in the ground where building once stood if (psDel->visible[selectedPlayer] && !resourceFound && !bMinor) diff --git a/src/structure.h b/src/structure.h index dd437322c04..a657c59cc0e 100644 --- a/src/structure.h +++ b/src/structure.h @@ -112,7 +112,7 @@ extern bool structureStatsShutDown(void); int requestOpenGate(STRUCTURE *psStructure); -int32_t structureDamage(STRUCTURE *psStructure, UDWORD damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass); +int32_t structureDamage(STRUCTURE *psStructure, unsigned damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass, unsigned impactTime); extern void structureBuild(STRUCTURE *psStructure, DROID *psDroid, int buildPoints, int buildRate = 1); extern void structureDemolish(STRUCTURE *psStructure, DROID *psDroid, int buildPoints); extern bool structureRepair(STRUCTURE *psStruct, DROID *psDroid, int buildPoints); @@ -131,7 +131,7 @@ STRUCTURE *buildBlueprint(STRUCTURE_STATS const *psStats, int32_t x, int32_t y, void structureUpdate(STRUCTURE *psBuilding, bool mission); /* Remove a structure and free it's memory */ -extern bool destroyStruct(STRUCTURE *psDel); +bool destroyStruct(STRUCTURE *psDel, unsigned impactTime); // remove a structure from a game without any visible effects // bDestroy = true if the object is to be destroyed