| | 1 | #include "system.h" |
| | 2 | #include "stratdef.h" |
| | 3 | #include "bh_deathvol.h" |
| | 4 | #include "dynamics.h" |
| | 5 | #include "weapons.h" |
| | 6 | #include <assert.h> |
| | 7 | #include "equipmnt.h" |
| | 8 | #include <stdlib.h> |
| | 9 | |
| | 10 | extern int NumActiveBlocks; |
| | 11 | extern DISPLAYBLOCK* ActiveBlockList[]; |
| | 12 | |
| | 13 | void DeathVolumeBehaveInit(void* bhdata,STRATEGYBLOCK* sbptr) |
| | 14 | { |
| | 15 | assert(sbptr); |
| | 16 | assert(bhdata); |
| | 17 | |
| | 18 | DEATH_VOLUME_BEHAV_BLOCK* dv_bhv = malloc(sizeof(DEATH_VOLUME_BEHAV_BLOCK)); |
| | 19 | |
| | 20 | if(dv_bhv) |
| | 21 | { |
| | 22 | sbptr->dataptr = dv_bhv; |
| | 23 | dv_bhv->bhvr_type = I_BehaviourDeathVolume; |
| | 24 | DEATH_VOLUME_TOOLS_TEMPLATE* dv_tt = (DEATH_VOLUME_TOOLS_TEMPLATE*)bhdata; |
| | 25 | //copy stuff from tools template |
| | 26 | COPY_NAME(sbptr->SBname, dv_tt->nameID); |
| | 27 | dv_bhv->volume_min = dv_tt->volume_min; |
| | 28 | dv_bhv->volume_max = dv_tt->volume_max; |
| | 29 | dv_bhv->damage_per_second = dv_tt->damage_per_second; |
| | 30 | dv_bhv->active = dv_tt->active; |
| | 31 | dv_bhv->collision_required = dv_tt->collision_required; |
| | 32 | } |
| | 33 | else |
| | 34 | { |
| | 35 | RemoveBehaviourStrategy(sbptr); |
| | 36 | } |
| | 37 | } |
| | 38 | |
| | 39 | void DeathVolumeBehaveFun(STRATEGYBLOCK* vol_sbptr) |
| | 40 | { |
| | 41 | assert(vol_sbptr); |
| | 42 | DEATH_VOLUME_BEHAV_BLOCK* dv_bhv = (DEATH_VOLUME_BEHAV_BLOCK*)vol_sbptr->dataptr; |
| | 43 | assert((dv_bhv->bhvr_type == I_BehaviourDeathVolume)); |
| | 44 | |
| | 45 | if(dv_bhv->active) |
| | 46 | { |
| | 47 | int miny,maxy; |
| | 48 | int i=0; |
| | 49 | |
| | 50 | for(; i < NumActiveBlocks; i++) |
| | 51 | { |
| | 52 | //search for objects that have has a collision this frame |
| | 53 | //(or all objects if collisions aren't required) |
| | 54 | DISPLAYBLOCK* dptr = ActiveBlockList[i]; |
| | 55 | STRATEGYBLOCK* sbPtr = ActiveBlockList[i]->ObStrategyBlock; |
| | 56 | |
| | 57 | if(!sbPtr || !sbPtr->DynPtr) |
| | 58 | continue; |
| | 59 | |
| | 60 | DYNAMICSBLOCK* dynPtr = sbPtr->DynPtr; |
| | 61 | |
| | 62 | if(dv_bhv->collision_required) |
| | 63 | { |
| | 64 | if(!dynPtr->CollisionReportPtr) |
| | 65 | continue; |
| | 66 | } |
| | 67 | |
| | 68 | //is the object within the death volume? |
| | 69 | //check a vertical line against the death volume's bounding box |
| | 70 | |
| | 71 | //first check the object's centre x and centre z values against the volume |
| | 72 | if(dptr->ObWorld.vx < dv_bhv->volume_min.vx) |
| | 73 | continue; |
| | 74 | |
| | 75 | if(dptr->ObWorld.vx > dv_bhv->volume_max.vx) |
| | 76 | continue; |
| | 77 | |
| | 78 | if(dptr->ObWorld.vz < dv_bhv->volume_min.vz) |
| | 79 | continue; |
| | 80 | |
| | 81 | if(dptr->ObWorld.vz > dv_bhv->volume_max.vz) |
| | 82 | continue; |
| | 83 | |
| | 84 | //now check the object's vertical extents for overlap with the death volume bounding box |
| | 85 | miny = dptr->ObWorld.vy + dptr->extent.min_y; |
| | 86 | maxy = dptr->ObWorld.vy + dptr->extent.max_y; |
| | 87 | |
| | 88 | if(max(miny, dv_bhv->volume_min.vy) > min(maxy, dv_bhv->volume_max.vy)) |
| | 89 | continue; |
| | 90 | /* |
| | 91 | if(dynPtr->Position.vx > dv_bhv->volume_min.vx && |
| | 92 | dynPtr->Position.vx < dv_bhv->volume_max.vx && |
| | 93 | dynPtr->Position.vz > dv_bhv->volume_min.vz && |
| | 94 | dynPtr->Position.vz < dv_bhv->volume_max.vz && |
| | 95 | dynPtr->Position.vy > dv_bhv->volume_min.vy && |
| | 96 | dynPtr->Position.vy < dv_bhv->volume_max.vy) |
| | 97 | */ |
| | 98 | { |
| | 99 | //finally see if the object is one of the types that can be harmed by the death volume |
| | 100 | switch(sbPtr->type) |
| | 101 | { |
| | 102 | case I_BehaviourAlien: |
| | 103 | case I_BehaviourMarine: |
| | 104 | case I_BehaviourMarinePlayer: |
| | 105 | case I_BehaviourPredatorPlayer: |
| | 106 | case I_BehaviourAlienPlayer: |
| | 107 | case I_BehaviourPredator: |
| | 108 | case I_BehaviourFaceHugger: |
| | 109 | case I_BehaviourXenoborg: |
| | 110 | case I_BehaviourQueenAlien: |
| | 111 | { |
| | 112 | extern int myNetworkKillerId; |
| | 113 | extern int AVPDPNetID; |
| | 114 | |
| | 115 | //this is a neutral source of damage (for cooperative multiplayer games) |
| | 116 | myNetworkKillerId = 0; |
| | 117 | |
| | 118 | if(dv_bhv->damage_per_second) |
| | 119 | { |
| | 120 | VECTORCH direction = {0, -ONE_FIXED, 0}; |
| | 121 | DAMAGE_PROFILE damage = {0,0,1,0,0,0,0,0,0,0,0,AMMO_NONE}; |
| | 122 | damage.Penetrative = dv_bhv->damage_per_second; |
| | 123 | CauseDamageToObject(sbPtr, &damage, NormalFrameTime, &direction); |
| | 124 | } |
| | 125 | else |
| | 126 | { |
| | 127 | //kill the creature/player |
| | 128 | VECTORCH direction = {0, -ONE_FIXED, 0}; |
| | 129 | CauseDamageToObject(sbPtr, &damage_profiles[CERTAINDEATH], ONE_FIXED, &direction); |
| | 130 | } |
| | 131 | |
| | 132 | //reset network killer id |
| | 133 | myNetworkKillerId = AVPDPNetID; |
| | 134 | } |
| | 135 | default: |
| | 136 | break; |
| | 137 | } |
| | 138 | } |
| | 139 | } |
| | 140 | } |
| | 141 | } |
| | 142 | |
| | 143 | /*--------------------** |
| | 144 | ** Loading and Saving ** |
| | 145 | **--------------------*/ |
| | 146 | #include "savegame.h" |
| | 147 | |
| | 148 | typedef struct death_volume_save_block |
| | 149 | { |
| | 150 | SAVE_BLOCK_STRATEGY_HEADER header; |
| | 151 | |
| | 152 | int active; |
| | 153 | |
| | 154 | } DEATH_VOLUME_SAVE_BLOCK; |
| | 155 | |
| | 156 | void LoadStrategy_DeathVolume(SAVE_BLOCK_STRATEGY_HEADER* header) |
| | 157 | { |
| | 158 | DEATH_VOLUME_SAVE_BLOCK* block = (DEATH_VOLUME_SAVE_BLOCK*) header; |
| | 159 | |
| | 160 | //check the size of the save block |
| | 161 | if(header->size != sizeof(*block)) |
| | 162 | return; |
| | 163 | |
| | 164 | //find the existing strategy block |
| | 165 | STRATEGYBLOCK* sbPtr = FindSBWithName(header->SBname); |
| | 166 | |
| | 167 | if(!sbPtr) |
| | 168 | return; |
| | 169 | |
| | 170 | //make sure the strategy found is of the right type |
| | 171 | if(sbPtr->type != I_BehaviourDeathVolume) |
| | 172 | return; |
| | 173 | |
| | 174 | DEATH_VOLUME_BEHAV_BLOCK* dv_bhv = (DEATH_VOLUME_BEHAV_BLOCK*)sbPtr->dataptr; |
| | 175 | |
| | 176 | //start copying stuff |
| | 177 | dv_bhv->active = block->active; |
| | 178 | } |
| | 179 | |
| | 180 | void SaveStrategy_DeathVolume(STRATEGYBLOCK* sbPtr) |
| | 181 | { |
| | 182 | DEATH_VOLUME_SAVE_BLOCK *block; |
| | 183 | DEATH_VOLUME_BEHAV_BLOCK* dv_bhv = (DEATH_VOLUME_BEHAV_BLOCK*)sbPtr->dataptr; |
| | 184 | |
| | 185 | GET_STRATEGY_SAVE_BLOCK(block,sbPtr); |
| | 186 | |
| | 187 | //start copying stuff |
| | 188 | block->active = dv_bhv->active; |
| | 189 | } |