From 3932fd68a3dc121c8e5c76a0746ef56eff7e89c2 Mon Sep 17 00:00:00 2001 From: q3rally Date: Fri, 17 Jun 2011 20:27:16 +0000 Subject: [PATCH] Several Changes. New type of breakables. --- engine/code/cgame/cg_effects.c | 558 ++++++++++++++++----------------- engine/code/cgame/cg_event.c | 98 ++++-- engine/code/game/bg_public.h | 17 +- engine/code/game/g_combat.c | 26 +- engine/code/game/g_mover.c | 60 ++++ engine/code/game/g_spawn.c | 14 +- engine/code/game/g_utils.c | 33 ++ q3rallycode.ppr | 90 +----- 8 files changed, 459 insertions(+), 437 deletions(-) diff --git a/engine/code/cgame/cg_effects.c b/engine/code/cgame/cg_effects.c index d7e16c40..0d1a7d7b 100644 --- a/engine/code/cgame/cg_effects.c +++ b/engine/code/cgame/cg_effects.c @@ -847,280 +847,11 @@ void CG_BigExplode( vec3_t playerOrigin ) { } /* -=================================================== -CG_LightningArc - -Generates an arc of lightning between -two abitary vectors -=================================================== -*/ - -void CG_LightningArc( vec3_t start, vec3_t end ) { - refEntity_t arc; - - memset( &arc, 0, sizeof( arc ) ); - arc.reType = RT_LIGHTNING; - arc.customShader = cgs.media.lightningShader; - - VectorCopy( start, arc.origin ); - VectorCopy( end, arc.oldorigin ); - - trap_R_AddRefEntityToScene( &arc ); -} - -/* - ================== - CG_LaunchShard - ================== - */ - void CG_LaunchShard( vec3_t origin, vec3_t velocity, qhandle_t hModel ) { - int bounce; - localEntity_t *le; - refEntity_t *re; - - le = CG_AllocLocalEntity(); - re = &le->refEntity; - - le->leType = LE_FRAGMENT; - le->startTime = cg.time; - le->endTime = le->startTime + 30000 + random() * 3000; - - VectorCopy( origin, re->origin ); - AxisCopy( axisDefault, re->axis ); - re->hModel = hModel; - - le->pos.trType = TR_GRAVITY; - VectorCopy( origin, le->pos.trBase ); - VectorCopy( velocity, le->pos.trDelta ); - le->pos.trTime = cg.time; - - bounce = le->bounceFactor; - bounce = 0.3; - - le->leFlags = LEF_TUMBLE; - le->leBounceSoundType = LEBS_BRASS; - le->leMarkType = LEMT_NONE; - } - - - - - /* - =================== - CG_BreakGlass - - Breaks our brush and generates a few models on launches them all over the map :) - =================== - */ - - #define GLASS_VELOCITY 175 //175 - #define GLASS_JUMP 125 //125 - - void CG_BreakGlass( vec3_t playerOrigin ) { - vec3_t origin, velocity; - int value; - int count = 20; //20 - int states[] = {1,2,3}; - int numstates = sizeof(states)/sizeof(states[0]); - - while ( count-- ) { - - value = states[rand()%numstates]; - VectorCopy( playerOrigin, origin ); - velocity[0] = crandom() * 165; //165 - velocity[1] = crandom() * 125; //125 - //velocity[2] = 0; //GLASS_JUMP + crandom() * 1; //165 - velocity[2] = GLASS_JUMP + crandom() * 165; //165 - - switch (value) { - case 1: - CG_LaunchShard( origin, velocity, cgs.media.glass01 ); - break; - case 2: - CG_LaunchShard( origin, velocity, cgs.media.glass02 ); - break; - case 3: - CG_LaunchShard( origin, velocity, cgs.media.glass03 ); - break; - } - } -} - - /* - ================== - CG_LaunchWood - ================== - */ - void CG_LaunchWood( vec3_t origin, vec3_t velocity, qhandle_t hModel ) { - int bounce; - localEntity_t *le; - refEntity_t *re; - - le = CG_AllocLocalEntity(); - re = &le->refEntity; - - le->leType = LE_FRAGMENT; - le->startTime = cg.time; - le->endTime = le->startTime + 30000 + random() * 3000; - - VectorCopy( origin, re->origin ); - AxisCopy( axisDefault, re->axis ); - re->hModel = hModel; - - le->pos.trType = TR_GRAVITY; - VectorCopy( origin, le->pos.trBase ); - VectorCopy( velocity, le->pos.trDelta ); - le->pos.trTime = cg.time; - - bounce = le->bounceFactor; - bounce = 0.9; //0.3 - //newq3ball - /* pm->ps->velocity[2] = -vel * 0.5; //2 - if (pm->ps->velocity[2] <= 0.001) { - pm->ps->velocity[2] = 0; - */ - //endnew - le->leFlags = LEF_TUMBLE; - le->leBounceSoundType = LEBS_BRASS; - le->leMarkType = LEMT_NONE; - } - - - - - /* - =================== - CG_BREAKWOOD - - Breaks our brush and generates a few (here 1 model) on launches them all over the map :) - =================== - */ - - #define BOX_VELOCITY 60 //175 - #define BOX_JUMP 85 //125 - - void CG_BREAKWOOD( vec3_t playerOrigin ) { - vec3_t origin, velocity; - int value; - int count = 8; //20 - int states[] = {1,2,3}; - int numstates = sizeof(states)/sizeof(states[0]); - - while ( count-- ) { - - value = states[rand()%numstates]; - VectorCopy( playerOrigin, origin ); - velocity[0] = crandom() * 80; //165 - velocity[1] = crandom() * 125; //125 - velocity[2] = BOX_JUMP + crandom() * 165; //165 - //velocity[2] = 165; //165 - //newq3ball -// velocity[2] = -velocity[0] * 0.5; //2 -// if (velocity[2] <= 0.001) { - // velocity[2] = 0; -// } - //endnew - switch (value) { - case 1: - CG_LaunchWood( origin, velocity, cgs.media.wood01 ); - break; - case 2: - CG_LaunchWood( origin, velocity, cgs.media.wood02 ); - break; - case 3: - CG_LaunchWood( origin, velocity, cgs.media.wood03 ); - break; - } - } -} - - /* - ================== - CG_LaunchMetal - ================== - */ - void CG_LaunchMetal( vec3_t origin, vec3_t velocity, qhandle_t hModel ) { - int bounce; - localEntity_t *le; - refEntity_t *re; - - le = CG_AllocLocalEntity(); - re = &le->refEntity; - - le->leType = LE_FRAGMENT; - le->startTime = cg.time; - le->endTime = le->startTime + 30000 + random() * 3000; - - VectorCopy( origin, re->origin ); - AxisCopy( axisDefault, re->axis ); - re->hModel = hModel; - - le->pos.trType = TR_GRAVITY; - VectorCopy( origin, le->pos.trBase ); - VectorCopy( velocity, le->pos.trDelta ); - le->pos.trTime = cg.time; - - bounce = le->bounceFactor; - bounce = 0.9; //0.3 - - le->leFlags = LEF_TUMBLE; - le->leBounceSoundType = LEBS_BRASS; - le->leMarkType = LEMT_NONE; - } - - -/* - =================== - CG_BREAKMETAL - - Breaks our brush and generates a few (here 1 model) on launches them all over the map :) - =================== - */ - -#define METAL_VELOCITY 60 //175 - #define METAL_JUMP 85 //125 - - void CG_BREAKMETAL( vec3_t playerOrigin ) { - vec3_t origin, velocity; - int value; - int count = 8; //20 - int states[] = {1,2,3}; - int numstates = sizeof(states)/sizeof(states[0]); - - while ( count-- ) { - - value = states[rand()%numstates]; - VectorCopy( playerOrigin, origin ); - velocity[0] = crandom() * 80; //165 - velocity[1] = crandom() * 125; //125 - velocity[2] = METAL_JUMP + crandom() * 165; //165 - //velocity[2] = 165; //165 - //newq3ball -// velocity[2] = -velocity[0] * 0.5; //2 -// if (velocity[2] <= 0.001) { - // velocity[2] = 0; -// } - //endnew - switch (value) { - case 1: - CG_LaunchMetal( origin, velocity, cgs.media.metal01 ); - break; - case 2: - CG_LaunchMetal( origin, velocity, cgs.media.metal02 ); - break; - case 3: - CG_LaunchMetal( origin, velocity, cgs.media.metal03 ); - break; - } - } -} - - /* ================== -CG_LaunchDebris +CG_LaunchFragment ================== */ -void CG_LaunchDebris( vec3_t origin, vec3_t velocity, qhandle_t hModel ) { +void CG_LaunchFragment( vec3_t origin, vec3_t velocity, leTrailType_t trailType, qhandle_t hModel ) { localEntity_t *le; refEntity_t *re; @@ -1142,8 +873,16 @@ void CG_LaunchDebris( vec3_t origin, vec3_t velocity, qhandle_t hModel ) { le->bounceFactor = 0.6f; - le->leBounceSoundType = LEBS_DEBRIS; - //le->leMarkType = LEMT_BLOOD; + if ( trailType == LETT_BLOOD ) { + le->leBounceSoundType = LEBS_BLOOD; + le->leMarkType = LEMT_BLOOD; + } else { + le->leBounceSoundType = LEBS_NONE; + le->leMarkType = LEMT_NONE; + } + + + le->leTrailType = trailType; } /* @@ -1153,7 +892,7 @@ CG_ShowDebris Generated a bunch of debris launching out from an entity's location =================== */ -void CG_ShowDebris( vec3_t srcOrigin, int count, int type ) { +void CG_ShowDebris( vec3_t srcOrigin, int count, int evType ) { vec3_t origin, velocity; int i, r; @@ -1162,44 +901,275 @@ void CG_ShowDebris( vec3_t srcOrigin, int count, int type ) { velocity[0] = crandom()*GIB_VELOCITY; velocity[1] = crandom()*GIB_VELOCITY; velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY; - r = rand() % 8; - if ( type == EV_EMIT_DEBRIS_NORMAL ) { + if ( evType == EV_EMIT_DEBRIS_LIGHT ) { + r = rand() % 8; if (r == 0) - CG_LaunchDebris( origin, velocity, cgs.media.debris1 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrislight1 ); else if (r == 1) - CG_LaunchDebris( origin, velocity, cgs.media.debris2 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrislight2 ); else if (r == 2) - CG_LaunchDebris( origin, velocity, cgs.media.debris3 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrislight3 ); else if (r == 3) - CG_LaunchDebris( origin, velocity, cgs.media.debris4 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrislight4 ); else if (r == 4) - CG_LaunchDebris( origin, velocity, cgs.media.debris5 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrislight5 ); else if (r == 5) - CG_LaunchDebris( origin, velocity, cgs.media.debris6 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrislight6 ); else if (r == 6) - CG_LaunchDebris( origin, velocity, cgs.media.debris7 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrislight7 ); else if (r == 7) - CG_LaunchDebris( origin, velocity, cgs.media.debris8 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrislight8 ); } - if ( type == EV_EMIT_DEBRIS_DARK ) { + if ( evType == EV_EMIT_DEBRIS_DARK ) { + r = rand() % 8; if (r == 0) - CG_LaunchDebris( origin, velocity, cgs.media.debrisdark1 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrisdark1 ); else if (r == 1) - CG_LaunchDebris( origin, velocity, cgs.media.debrisdark2 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrisdark2 ); else if (r == 2) - CG_LaunchDebris( origin, velocity, cgs.media.debrisdark3 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrisdark3 ); else if (r == 3) - CG_LaunchDebris( origin, velocity, cgs.media.debrisdark4 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrisdark4 ); else if (r == 4) - CG_LaunchDebris( origin, velocity, cgs.media.debrisdark5 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrisdark5 ); else if (r == 5) - CG_LaunchDebris( origin, velocity, cgs.media.debrisdark6 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrisdark6 ); else if (r == 6) - CG_LaunchDebris( origin, velocity, cgs.media.debrisdark7 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrisdark7 ); else if (r == 7) - CG_LaunchDebris( origin, velocity, cgs.media.debrisdark8 ); + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrisdark8 ); + } + + if ( evType == EV_EMIT_DEBRIS_LIGHT_LARGE ) { + r = rand() % 3; + if (r == 0) + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrislightlarge1 ); + else if (r == 1) + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrislightlarge2 ); + else if (r == 2) + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrislightlarge3 ); + } + + if ( evType == EV_EMIT_DEBRIS_DARK_LARGE ) { + r = rand() % 3; + if (r == 0) + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrisdarklarge1 ); + else if (r == 1) + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrisdarklarge2 ); + else if (r == 2) + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_CONCRETE, cgs.media.debrisdarklarge3 ); + } + + if ( evType == EV_EMIT_DEBRIS_WOOD ) { + r = rand() % 5; + if (r == 0) + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_WOOD, cgs.media.debriswood1 ); + else if (r == 1) + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_WOOD, cgs.media.debriswood2 ); + else if (r == 2) + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_WOOD, cgs.media.debriswood3 ); + else if (r == 3) + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_WOOD, cgs.media.debriswood4 ); + else if (r == 4) + CG_LaunchFragment( origin, velocity, LETT_DEBRIS_WOOD, cgs.media.debriswood5 ); + } + + if ( evType == EV_EMIT_DEBRIS_FLESH ) { + r = rand() % 10; + if (r == 0) + CG_LaunchFragment( origin, velocity, LETT_BLOOD, cgs.media.gibSkull ); + else if (r == 1) + CG_LaunchFragment( origin, velocity, LETT_BLOOD, cgs.media.gibBrain ); + else if (r == 2) + CG_LaunchFragment( origin, velocity, LETT_BLOOD, cgs.media.gibAbdomen ); + else if (r == 3) + CG_LaunchFragment( origin, velocity, LETT_BLOOD, cgs.media.gibArm ); + else if (r == 4) + CG_LaunchFragment( origin, velocity, LETT_BLOOD, cgs.media.gibChest ); + else if (r == 5) + CG_LaunchFragment( origin, velocity, LETT_BLOOD, cgs.media.gibFist ); + else if (r == 6) + CG_LaunchFragment( origin, velocity, LETT_BLOOD, cgs.media.gibFoot ); + else if (r == 7) + CG_LaunchFragment( origin, velocity, LETT_BLOOD, cgs.media.gibForearm ); + else if (r == 8) + CG_LaunchFragment( origin, velocity, LETT_BLOOD, cgs.media.gibIntestine ); + else if (r == 9) + CG_LaunchFragment( origin, velocity, LETT_BLOOD, cgs.media.gibLeg ); + } + + if ( evType == EV_EMIT_DEBRIS_GLASS ) { + r = rand() % 15; //we're getting twice the number of small shards as big shards this way + if (r == 0 || r == 1) + CG_LaunchFragment( origin, velocity, LETT_NONE, cgs.media.debrisglass1 ); + else if (r == 2 || r == 3) + CG_LaunchFragment( origin, velocity, LETT_NONE, cgs.media.debrisglass2 ); + else if (r == 4 || r == 5) + CG_LaunchFragment( origin, velocity, LETT_NONE, cgs.media.debrisglass3 ); + else if (r == 6 || r == 7) + CG_LaunchFragment( origin, velocity, LETT_NONE, cgs.media.debrisglass4 ); + else if (r == 8 || r == 9) + CG_LaunchFragment( origin, velocity, LETT_NONE, cgs.media.debrisglass5 ); + else if (r == 10) + CG_LaunchFragment( origin, velocity, LETT_NONE, cgs.media.debrisglasslarge1 ); + else if (r == 11) + CG_LaunchFragment( origin, velocity, LETT_NONE, cgs.media.debrisglasslarge2 ); + else if (r == 12) + CG_LaunchFragment( origin, velocity, LETT_NONE, cgs.media.debrisglasslarge3 ); + else if (r == 13) + CG_LaunchFragment( origin, velocity, LETT_NONE, cgs.media.debrisglasslarge4 ); + else if (r == 14) + CG_LaunchFragment( origin, velocity, LETT_NONE, cgs.media.debrisglasslarge5 ); } } -} \ No newline at end of file +} + + +/* +=================== +CG_StartEarthquake + +Starts an earthquake effect +=================== +*/ +int flagEarthquake = qfalse; +int earthquakeIntensity = 0; +int earthquakeStoptime = 0; + +void CG_StartEarthquake(int intensity, int duration) +{ + flagEarthquake = qtrue; + if ( intensity < earthquakeIntensity ) + return; + + earthquakeIntensity = intensity; + earthquakeStoptime = cg.time + duration; +} + +void CG_Earthquake() +{ + static float terremotoX, terremotoY, terremotoZ; + static terremotoTime = 0; + float realInt; + + if ( !flagEarthquake ) + return; + + if ( earthquakeStoptime < cg.time ) + { + flagEarthquake = qfalse; + earthquakeIntensity = 0; + return; + } + + if ( terremotoTime < cg.time ) + { + terremotoTime = cg.time += 50; + realInt = ((float)earthquakeIntensity + 1.0) / 2.0; + terremotoX = random() * realInt - realInt / 2; + terremotoY = random() * realInt - realInt / 2; + terremotoZ = random() * realInt - realInt / 2; + } + cg.refdefViewAngles[0] += terremotoX; + cg.refdefViewAngles[1] += terremotoY; + cg.refdefViewAngles[2] += terremotoZ; + AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis ); +} + +/* +=================== +CG_ExplosionParticles + +Shows particles +=================== +*/ +void CG_Particles( vec3_t origin, int count, int speed, int lifetime, int radius, int type, byte r, byte g, byte b ) { + int jump; // amount to nudge the particles trajectory vector up by + qhandle_t shader; // shader to use for the particles + int index; + vec3_t randVec, tempVec; + qboolean moveUp; + + //jump = 70; + jump = speed; + shader = cgs.media.sparkShader; + + for ( index = 0; index < count; index++ ) { + localEntity_t *le; + refEntity_t *re; + + le = CG_AllocLocalEntity(); //allocate a local entity + re = &le->refEntity; + le->leFlags = LEF_PUFF_DONT_SCALE; //don't change the particle size + le->leType = LE_MOVE_SCALE_FADE; // particle should fade over time + le->startTime = cg.time; // set the start time of the particle to the current time + le->endTime = cg.time + lifetime + (random() * (lifetime / 2)); //life time will be anywhere between [lifetime] and [lifetime * 1.5] + le->lifeRate = 1.0 / ( le->endTime - le->startTime ); + re = &le->refEntity; + re->shaderTime = cg.time / 1000.0f; + re->reType = RT_SPRITE; + re->rotation = 0; + re->radius = radius; + re->customShader = shader; + re->shaderRGBA[0] = r; + re->shaderRGBA[1] = g; + re->shaderRGBA[2] = b; + re->shaderRGBA[3] = 0xFF; + le->color[3] = 1.0; + if ( type == PT_GRAVITY ) + le->pos.trType = TR_GRAVITY; // moves in a gravity affected arc + else + le->pos.trType = TR_LINEAR; // moves in straight line, outward from the origin + le->pos.trTime = cg.time; + VectorCopy( origin, le->pos.trBase ); + VectorCopy( origin, re->origin ); + + tempVec[0] = crandom(); //between 1 and -1 + tempVec[1] = crandom(); + tempVec[2] = crandom(); + VectorNormalize(tempVec); + VectorScale(tempVec, speed, randVec); + + if ( type == PT_GRAVITY || type == PT_LINEAR_UP ) + moveUp = qtrue; + else if ( type == PT_LINEAR_DOWN ) + moveUp = qfalse; + else if (crandom() < 0) + moveUp = qtrue; + else + moveUp = qfalse; + + + if (moveUp) + randVec[2] += jump; //nudge the particles up a bit + else + randVec[2] -= jump; //nudge the particles down a bit + + VectorCopy( randVec, le->pos.trDelta ); + } +} + +/* +=================== +CG_ParticlesFromEntityState + +Takes entitystate and extracts data inside to use for CG_Particles. +es->constantLight is used for the color of the particles. +es->eventParm is used for the number of particles. +es->generic1 is used for the speed of the particles. +=================== +*/ +void CG_ParticlesFromEntityState( vec3_t origin, int type, entityState_t *es) { + byte r, g, b; + int lifetime = 3000; + int radius = 3; + int speed = es->generic1; + + r = es->constantLight & 255; + g = ( es->constantLight >> 8 ) & 255; + b = ( es->constantLight >> 16 ) & 255; + + CG_Particles( origin, es->eventParm, speed, lifetime, radius, type, r, g, b ); +} diff --git a/engine/code/cgame/cg_event.c b/engine/code/cgame/cg_event.c index 3b29173b..4ae06460 100644 --- a/engine/code/cgame/cg_event.c +++ b/engine/code/cgame/cg_event.c @@ -29,7 +29,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifdef MISSIONPACK // bk001205 #include "../../ui/menudef.h" #endif - //========================================================================== /* @@ -1344,26 +1343,7 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { // Q3Rally Code END break; -// Q3Rally Code Start - case EV_BREAK_GLASS: - DEBUGNAME("EV_BREAK_GLASS"); - trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.glassSound ); - CG_BreakGlass( cent->lerpOrigin ); - break; - case EV_BREAKWOOD: - DEBUGNAME("EV_BREAKWOOD"); - trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.woodSound ); - CG_BREAKWOOD( cent->lerpOrigin ); - break; - - case EV_BREAKMETAL: - DEBUGNAME("EV_BREAKMETAL"); - trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.metalSound ); - CG_BREAKMETAL( cent->lerpOrigin ); - break; - -// Q3Rally Code END case EV_STOPLOOPINGSOUND: DEBUGNAME("EV_STOPLOOPINGSOUND"); @@ -1375,15 +1355,83 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { DEBUGNAME("EV_DEBUG_LINE"); CG_Beam( cent ); break; - - case EV_EMIT_DEBRIS_NORMAL: - DEBUGNAME("EV_EMIT_DEBRIS_NORMAL"); - CG_ShowDebris( cent->lerpOrigin, cent->currentState.eventParm, EV_EMIT_DEBRIS_NORMAL ); + + case EV_EMIT_DEBRIS_LIGHT: + DEBUGNAME("EV_EMIT_DEBRIS_LIGHT"); + CG_ShowDebris( cent->lerpOrigin, es->eventParm, EV_EMIT_DEBRIS_LIGHT ); break; case EV_EMIT_DEBRIS_DARK: DEBUGNAME("EV_EMIT_DEBRIS_DARK"); - CG_ShowDebris( cent->lerpOrigin, cent->currentState.eventParm, EV_EMIT_DEBRIS_DARK ); + CG_ShowDebris( cent->lerpOrigin, es->eventParm, EV_EMIT_DEBRIS_DARK ); + break; + + case EV_EMIT_DEBRIS_LIGHT_LARGE: + DEBUGNAME("EV_EMIT_DEBRIS_LIGHT_LARGE"); + CG_ShowDebris( cent->lerpOrigin, es->eventParm, EV_EMIT_DEBRIS_LIGHT_LARGE ); + break; + + case EV_EMIT_DEBRIS_DARK_LARGE: + DEBUGNAME("EV_EMIT_DEBRIS_DARK_LARGE"); + CG_ShowDebris( cent->lerpOrigin, es->eventParm, EV_EMIT_DEBRIS_DARK_LARGE ); + break; + + case EV_EMIT_DEBRIS_WOOD: + DEBUGNAME("EV_EMIT_DEBRIS_WOOD"); + CG_ShowDebris( cent->lerpOrigin, es->eventParm, EV_EMIT_DEBRIS_WOOD ); + break; + + case EV_EMIT_DEBRIS_FLESH: + DEBUGNAME("EV_EMIT_DEBRIS_FLESH"); + CG_ShowDebris( cent->lerpOrigin, es->eventParm, EV_EMIT_DEBRIS_FLESH ); + break; + + case EV_EMIT_DEBRIS_GLASS: + DEBUGNAME("EV_EMIT_DEBRIS_GLASS"); + CG_ShowDebris( cent->lerpOrigin, es->eventParm, EV_EMIT_DEBRIS_GLASS ); + break; + + case EV_EARTHQUAKE: + DEBUGNAME("EV_EARTHQUAKE"); + CG_StartEarthquake((es->eventParm & 0x0F) + 1, ((1 + ((es->eventParm & 0xF0) >> 4)) * 2000) + 1000); + break; + + case EV_EXPLOSION: + DEBUGNAME("EV_EXPLOSION"); + + // show plume (if enabled) + if ( cg_oldRocket.integer == 0 ) { + dir[0] = 0; + dir[1] = 0; + dir[2] = 25; + CG_ParticleExplosion( "explode1", cent->lerpOrigin, dir, 1400, 20, 30 ); + } + + // show explosion + dir[0] = 0; + dir[1] = 0; + dir[2] = 0; + CG_MakeExplosion( cent->lerpOrigin, dir, cgs.media.dishFlashModel, cgs.media.rocketExplosionShader, 1000, qtrue ); + break; + + case EV_PARTICLES_GRAVITY: + DEBUGNAME("EV_PARTICLES_GRAVITY"); + CG_ParticlesFromEntityState( cent->lerpOrigin, PT_GRAVITY, es ); + break; + + case EV_PARTICLES_LINEAR: + DEBUGNAME("EV_PARTICLES_LINEAR"); + CG_ParticlesFromEntityState( cent->lerpOrigin, PT_LINEAR_BOTH, es ); + break; + + case EV_PARTICLES_LINEAR_UP: + DEBUGNAME("EV_PARTICLES_LINEAR_UP"); + CG_ParticlesFromEntityState( cent->lerpOrigin, PT_LINEAR_UP, es ); + break; + + case EV_PARTICLES_LINEAR_DOWN: + DEBUGNAME("EV_PARTICLES_LINEAR_DOWN"); + CG_ParticlesFromEntityState( cent->lerpOrigin, PT_LINEAR_DOWN, es ); break; default: diff --git a/engine/code/game/bg_public.h b/engine/code/game/bg_public.h index 5bb9f30b..66b9756d 100644 --- a/engine/code/game/bg_public.h +++ b/engine/code/game/bg_public.h @@ -618,10 +618,21 @@ typedef enum { EV_TAUNT_GUARDBASE, EV_TAUNT_PATROL, - EV_EMIT_DEBRIS_NORMAL, // a target_debrisemitter that emits light concrete is triggered - EV_EMIT_DEBRIS_DARK // a target_debrisemitter that emits dark concrete is triggered - + EV_EMIT_DEBRIS_LIGHT, // emit light concrete chunks + EV_EMIT_DEBRIS_DARK, // emit dark concrete chunks + EV_EMIT_DEBRIS_LIGHT_LARGE, // emit light large concrete chunks + EV_EMIT_DEBRIS_DARK_LARGE, // emit dark large concrete chunks + EV_EMIT_DEBRIS_WOOD, // emit wooden chunks + EV_EMIT_DEBRIS_FLESH, // emit gibs + EV_EMIT_DEBRIS_GLASS, // emite shards of glass + EV_EARTHQUAKE, + EV_EXPLOSION, + EV_PARTICLES_GRAVITY, + EV_PARTICLES_LINEAR, + EV_PARTICLES_LINEAR_UP, + EV_PARTICLES_LINEAR_DOWN, + } entity_event_t; diff --git a/engine/code/game/g_combat.c b/engine/code/game/g_combat.c index ab669e15..1fe800b7 100644 --- a/engine/code/game/g_combat.c +++ b/engine/code/game/g_combat.c @@ -935,32 +935,16 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, attacker = &g_entities[ENTITYNUM_WORLD]; } -// If we found a BreakGlass brush check and break it - if ( targ->s.eType == ET_BREAKGLASS ) { - targ->health -= damage; - G_BreakGlass( targ, point, mod ); - return; - } - // If we found breakable wood brush check and break it - if ( targ->s.eType == ET_BREAKWOOD ) { - targ->health -= damage; - G_BREAKWOOD( targ, point, mod ); - return; - } - -// If we found breakable metal brush check and break it - if ( targ->s.eType == ET_BREAKMETAL ) { - targ->health -= damage; - G_BREAKMETAL( targ, point, mod ); - return; - } - - // shootable doors / buttons don't actually have any health // Rotating Doors + // shootable doors / buttons don't actually have any health if ( targ->s.eType == ET_MOVER ) { if ( targ->use && (targ->moverState == MOVER_POS1 || targ->moverState == ROTATOR_POS1) ) { targ->use( targ, inflictor, attacker ); + } else if ( targ->use == NULL ) { // entity is a func_breakable + targ->health -= damage; + if (targ->health <= 0) + Break_Breakable(targ, attacker); } return; } diff --git a/engine/code/game/g_mover.c b/engine/code/game/g_mover.c index 1b9076ab..a296bb5d 100644 --- a/engine/code/game/g_mover.c +++ b/engine/code/game/g_mover.c @@ -1815,6 +1815,66 @@ void SP_func_static( gentity_t *ent ) { VectorCopy( ent->s.origin, ent->r.currentOrigin ); } +/* +=============================================================================== + +BREAKABLE + +=============================================================================== +*/ + +//other is the player that broke the func_breakable +void Break_Breakable(gentity_t *ent, gentity_t *other) { + vec3_t size; + vec3_t center; + int count = 0; + int spawnflags = 0; + gentity_t *tmp; + int type = EV_EMIT_DEBRIS_LIGHT; + + // Get the center of the glass (code donated by Perle) + VectorSubtract(ent->r.maxs, ent->r.mins, size); + VectorScale(size, 0.5, size); + VectorAdd(ent->r.mins, size, center); + + + ent->takedamage = qfalse; + ent->s.eType = ET_INVISIBLE; + G_UseTargets( ent, other ); + + //need to store properties of the entity in seperate variables because we're going to free the entity + if ( ent->count > 0) { + count = ent->count; + spawnflags = ent->spawnflags; + } + + G_FreeEntity( ent ); + + //spray out debris + if ( count > 0 ) { + tmp = G_TempEntity( center, PickDebrisType( spawnflags ) ); + tmp->s.eventParm = count; + } +} + + +/*QUAKED func_breakable (0 .5 .8) ? see PickDebrisType in g_util.c for spawnflags +A bmodel that just sits there, doing nothing. It is removed when it received a set amount of damage. +"model2" .md3 model to also draw +"color" constantLight color +"light" constantLight radius +"health" the amount of damage required before this entity is removed +*/ +void SP_func_breakable( gentity_t *ent ) { + trap_SetBrushModel( ent, ent->model ); + InitMover( ent ); + VectorCopy( ent->s.origin, ent->s.pos.trBase ); + VectorCopy( ent->s.origin, ent->r.currentOrigin ); + ent->takedamage = qtrue; + ent->use = NULL; + ent->r.contents = CONTENTS_SOLID; + ent->clipmask = MASK_SOLID; +} /* =============================================================================== diff --git a/engine/code/game/g_spawn.c b/engine/code/game/g_spawn.c index 58f145c2..aba9edfe 100644 --- a/engine/code/game/g_spawn.c +++ b/engine/code/game/g_spawn.c @@ -145,6 +145,7 @@ void SP_info_podium(gentity_t *ent); void SP_func_plat (gentity_t *ent); void SP_func_static (gentity_t *ent); +void SP_func_breakable (gentity_t *ent); void SP_func_rotating (gentity_t *ent); void SP_func_bobbing (gentity_t *ent); void SP_func_pendulum( gentity_t *ent ); @@ -152,11 +153,7 @@ void SP_func_button (gentity_t *ent); void SP_func_door (gentity_t *ent); void SP_func_train (gentity_t *ent); void SP_func_timer (gentity_t *self); -// Q3Rally Code Start -void SP_func_breakglass (gentity_t *ent); -void SP_func_breakwood (gentity_t *ent); -void SP_func_breakmetal (gentity_t *ent); -// Q3Rally Code END + void SP_trigger_always (gentity_t *ent); void SP_trigger_multiple (gentity_t *ent); @@ -179,6 +176,7 @@ void SP_target_position (gentity_t *ent); void SP_target_location (gentity_t *ent); void SP_target_push (gentity_t *ent); void SP_target_debrisemitter (gentity_t *ent); +void SP_target_earthquake (gentity_t *ent); void SP_light (gentity_t *self); void SP_info_null (gentity_t *self); @@ -249,10 +247,7 @@ spawn_t spawns[] = { {"func_train", SP_func_train}, {"func_group", SP_info_null}, {"func_timer", SP_func_timer}, // rename trigger_timer? - {"func_breakglass", SP_func_breakglass}, - {"func_breakwood", SP_func_breakwood}, - {"func_breakmetal", SP_func_breakmetal}, - + {"func_breakable", SP_func_breakable}, // Triggers are brush objects that cause an effect when contacted // by a living player, usually involving firing targets. @@ -281,6 +276,7 @@ spawn_t spawns[] = { {"target_location", SP_target_location}, {"target_push", SP_target_push}, {"target_debrisemitter", SP_target_debrisemitter}, + {"target_earthquake", SP_target_earthquake}, {"light", SP_light}, {"path_corner", SP_path_corner}, diff --git a/engine/code/game/g_utils.c b/engine/code/game/g_utils.c index ef2f1d28..c8075ec2 100644 --- a/engine/code/game/g_utils.c +++ b/engine/code/game/g_utils.c @@ -712,6 +712,39 @@ gentity_t *findradius (gentity_t *from, vec3_t org, float rad) return NULL; } +/* +================== +PickDebrisType +returns a type of debris based on the passed spawnflags value +================== +*/ +int PickDebrisType( int spawnflags ) { + + if ( spawnflags & 1 ) + return EV_EMIT_DEBRIS_LIGHT; + + if ( spawnflags & 2 ) + return EV_EMIT_DEBRIS_DARK; + + if ( spawnflags & 4 ) + return EV_EMIT_DEBRIS_LIGHT_LARGE; + + if ( spawnflags & 8 ) + return EV_EMIT_DEBRIS_DARK_LARGE; + + if ( spawnflags & 16 ) + return EV_EMIT_DEBRIS_WOOD; + + if ( spawnflags & 32 ) + return EV_EMIT_DEBRIS_FLESH; + + if ( spawnflags & 64 ) + return EV_EMIT_DEBRIS_GLASS; + + //if no compatible spawnflags supplied, return EV_EMIT_DEBRIS_LIGHT + return EV_EMIT_DEBRIS_LIGHT; +} + // Perle - Code helper function // qboolean visible( gentity_t *ent1, gentity_t *ent2 ) { diff --git a/q3rallycode.ppr b/q3rallycode.ppr index e9d76fc6..4588bed1 100644 --- a/q3rallycode.ppr +++ b/q3rallycode.ppr @@ -855,92 +855,12 @@ q3rallycode [Open project files] 0=engine\code\game\g_mover.c 1=engine\code\game\g_combat.c -2=engine\code\game\g_spawn.c -3=engine\code\cgame\cg_main.c -4=engine\code\cgame\cg_effects.c -5=engine\code\game\g_local.h -6=engine\code\game\g_misc.c -7=engine\code\cgame\cg_event.c -8=engine\code\cgame\cg_local.h -9=engine\code\ui\ui_main.c -10=engine\code\server\sv_main.c -11=engine\code\renderer\tr_public.h -12=engine\code\botlib\botlib.h -13=engine\code\client\cl_cgame.c -14=engine\code\client\client.h -15=engine\code\game\ai_main.c -16=engine\code\qcommon\common.c -17=engine\code\qcommon\qcommon.h -18=engine\code\server\server.h -19=engine\code\zlib\adler32.c -20=engine\ChangeLog -21=engine\code\qcommon\files.c [Selected Project Files] Main= -Selected=engine\code\game\g_mover.c +Selected=engine\code\game\g_combat.c [engine\code\game\g_mover.c] -TopLine=1659 -Caret=33,1676 +TopLine=1817 +Caret=21,1827 [engine\code\game\g_combat.c] -TopLine=931 -Caret=1,941 -[engine\code\game\g_spawn.c] -TopLine=235 -Caret=40,250 -[engine\code\cgame\cg_main.c] -TopLine=1178 -Caret=1,1206 -[engine\code\cgame\cg_effects.c] -TopLine=905 -Caret=1,919 -[engine\code\game\g_local.h] -TopLine=675 -Caret=1,691 -[engine\code\game\g_misc.c] -TopLine=751 -Caret=3,768 -[engine\code\cgame\cg_event.c] -TopLine=1337 -Caret=1,1351 -[engine\code\cgame\cg_local.h] -TopLine=1727 -Caret=54,1743 -[engine\code\ui\ui_main.c] -TopLine=3236 -Caret=1,3250 -[engine\code\server\sv_main.c] -TopLine=49 -Caret=1,49 -[engine\code\renderer\tr_public.h] -TopLine=135 -Caret=1,149 -[engine\code\botlib\botlib.h] -TopLine=477 -Caret=1,491 -[engine\code\client\cl_cgame.c] -TopLine=368 -Caret=1,382 -[engine\code\client\client.h] -TopLine=445 -Caret=1,459 -[engine\code\game\ai_main.c] -TopLine=1590 -Caret=1,1604 -[engine\code\qcommon\common.c] -TopLine=2473 -Caret=1,2487 -[engine\code\qcommon\qcommon.h] -TopLine=665 -Caret=1,679 -[engine\code\server\server.h] -TopLine=159 -Caret=1,173 -[engine\code\zlib\adler32.c] -TopLine=1 -Caret=1,1 -[engine\ChangeLog] -TopLine=61 -Caret=1,75 -[engine\code\qcommon\files.c] -TopLine=188 -Caret=34,201 +TopLine=1027 +Caret=14,959