diff --git a/client/cl_event.c b/client/cl_event.c index 6666729..c3a3807 100644 --- a/client/cl_event.c +++ b/client/cl_event.c @@ -230,8 +230,8 @@ void CL_EntityEvent (entity_state_t *ent) S_StartSound (NULL, ent->number, CHAN_WEAPON, clMedia.sfx_player_teleport, 1, ATTN_IDLE, 0); CL_TeleportParticles (ent->origin); break; - case EV_PLAYER_TELEPORT_Q1: - S_StartSound (NULL, ent->number, CHAN_WEAPON, clMedia.sfx_player_teleport_q1[rand()%5], 1, ATTN_IDLE, 0); + case EV_PLAYER_TELEPORT2: + S_StartSound (NULL, ent->number, CHAN_WEAPON, clMedia.sfx_player_teleport2[rand()%5], 1, ATTN_IDLE, 0); CL_TeleportParticles (ent->origin); break; case EV_FOOTSTEP: diff --git a/client/cl_main.c b/client/cl_main.c index 29bab6f..f3df086 100644 --- a/client/cl_main.c +++ b/client/cl_main.c @@ -605,7 +605,8 @@ CL_Connect_f */ void CL_Connect_f (void) { - char *server; + char *server, *p; + netadr_t serverAdr; if (Cmd_Argc() != 2) { @@ -625,8 +626,24 @@ void CL_Connect_f (void) server = Cmd_Argv (1); + // start quake2:// support + if (!strncmp (server, "quake2://", 9)) + server += 9; + + p = strchr (server, '/'); // remove trailing slash + if (p) + p[0] = '\0'; + // end quake2:// support + NET_Config (true); // allow remote + // validate server address + if (!NET_StringToAdr (server, &serverAdr)) + { + Com_Printf ("Bad server address: %s\n", server); + return; + } + CL_Disconnect (); cls.state = ca_connecting; @@ -1543,7 +1560,7 @@ void CL_InitLocal (void) cl_maxfps = Cvar_Get ("cl_maxfps", "90", 0); #ifdef CLIENT_SPLIT_NETFRAME - cl_async = Cvar_Get ("cl_async", "1", 0); + cl_async = Cvar_Get ("cl_async", "1", CVAR_ARCHIVE); net_maxfps = Cvar_Get ("net_maxfps", "60", 0); r_maxfps = Cvar_Get ("r_maxfps", "125", 0); #endif diff --git a/client/cl_tempent.c b/client/cl_tempent.c index b7e51f9..97177bf 100644 --- a/client/cl_tempent.c +++ b/client/cl_tempent.c @@ -203,10 +203,10 @@ void CL_RegisterTEntSounds (void) clMedia.sfx_player_land = S_RegisterSound ("player/land1.wav"); // player teleport clMedia.sfx_player_teleport = S_RegisterSound ("misc/tele1.wav"); - // Q1 player teleport (in rogue pak0.pak) + // Q1-style player teleport (in rogue pak0.pak) for (i=0; i<5; i++) { Com_sprintf (name, sizeof(name), "misc/r_tele%i.wav", i+1); - clMedia.sfx_player_teleport_q1[i] = S_RegisterSound (name); + clMedia.sfx_player_teleport2[i] = S_RegisterSound (name); } // item respawn clMedia.sfx_item_respawn = S_RegisterSound ("items/respawn1.wav"); diff --git a/client/client.h b/client/client.h index ef2a6ee..4b54b12 100644 --- a/client/client.h +++ b/client/client.h @@ -930,7 +930,7 @@ typedef struct { struct sfx_s *sfx_ladder[4]; struct sfx_s *sfx_player_land; struct sfx_s *sfx_player_teleport; - struct sfx_s *sfx_player_teleport_q1[5]; + struct sfx_s *sfx_player_teleport2[5]; struct sfx_s *sfx_item_respawn; struct model_s *mod_explode; diff --git a/game/g_ai.c b/game/g_ai.c index d44d601..47f4b47 100644 --- a/game/g_ai.c +++ b/game/g_ai.c @@ -414,7 +414,7 @@ qboolean visible (edict_t *self, edict_t *other) float dw; vec3_t v; - pfog = &level.fog; + pfog = &level.current_fog; VectorSubtract(spot2,spot1,v); r = VectorLength(v); switch(pfog->Model) diff --git a/game/g_fog.c b/game/g_fog.c index 9be3822..58c5ff2 100644 --- a/game/g_fog.c +++ b/game/g_fog.c @@ -32,8 +32,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // gi.WriteByte (fog_enable); // 1 = on, 0 = off // gi.WriteByte (fog_model); // 0, 1, or 2 // gi.WriteByte (fog_density); // 1-100 -// gi.WriteShort (fog_near); // >0, fog_near-64, < 5000 +// gi.WriteShort (fog_near); // >0, < fog_far +// gi.WriteShort (fog_far); // >fog_near-64, < 10000 // gi.WriteByte (fog_red); // 0-255 // gi.WriteByte (fog_green); // 0-255 // gi.WriteByte (fog_blue); // 0-255 @@ -43,7 +43,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. void Fog_Init (void) {} void Fog (edict_t *ent) {} -void Fog_Off (qboolean gameShutdown) {} +void Fog_Off (edict_t *ent) {} +void Fog_Off_Global (void) {} void Fog_ConsoleFog (void) {} void GLFog (void) {} void trig_fog_fade (edict_t *self) {} @@ -76,7 +77,7 @@ NEW FOG SYSTEM void Client_Fog_Off (edict_t *player_ent) { - if (!player_ent->client || player_ent->is_bot) + if (!player_ent || !player_ent->client || player_ent->is_bot) return; gi.WriteByte (svc_fog); // svc_fog = 21 @@ -84,7 +85,7 @@ void Client_Fog_Off (edict_t *player_ent) gi.WriteByte (0); // 0, 1, or 2 gi.WriteByte (0); // 1-100 gi.WriteShort (0); // >0, fog_near-64, < 5000 + gi.WriteShort (0); // >fog_near-64, < 10000 gi.WriteByte (0); // 0-255 gi.WriteByte (0); // 0-255 gi.WriteByte (0); // 0-255 @@ -158,16 +159,16 @@ void Fog_ConsoleFog (void) { // This routine is ONLY called for console fog commands - if(deathmatch->value || coop->value) + if (deathmatch->value || coop->value) return; - if(!level.active_fog) return; + if (!level.active_fog) return; - memcpy(&level.fog,&gfogs[0],sizeof(fog_t)); - pfog = &level.fog; + memcpy(&level.current_fog, &gfogs[0], sizeof(fog_t)); + pfog = &level.current_fog; // Force sensible values for linear: - if(pfog->Model==0 && pfog->Near==0. && pfog->Far==0.) + if ( (pfog->Model == 0) && (pfog->Near == 0.0f) && (pfog->Far == 0.0f) ) { pfog->Near=64; pfog->Far=1024; @@ -183,11 +184,14 @@ void Cmd_Fog_f (edict_t *ent) fog = &gfogs[0]; cmd = gi.argv(0); - if(gi.argc() < 2) + if (gi.argc() < 2) parm = NULL; else parm = gi.argv(1); + if (!ent || !ent->client || ent->is_bot) + return; + if (Q_stricmp (cmd, "fog_help") == 0 ) { gi.dprintf("Fog parameters for console only.\n" @@ -203,38 +207,38 @@ void Cmd_Fog_f (edict_t *ent) "Linear parameters:\n" "Fog_Near = fog start distance (>0 and < Fog_Far)\n" "Fog_Far = distance where objects are completely obscured\n" - " (<5000 and > Fog_Near)\n" + " (<10000 and > Fog_Near)\n" "Exponential parameters:\n" "Fog_Density Best results with values < 100\n\n" "Command without a value will show current setting\n"); } - else if(Q_stricmp (cmd, "fog_active") == 0 ) + else if (Q_stricmp (cmd, "fog_active") == 0 ) { - if(level.active_fog) + if (level.active_fog) { gi.dprintf("Active fog:\n" " Color: %f, %f, %f\n" " Model: %s\n", - level.fog.Color[0],level.fog.Color[1],level.fog.Color[2], - (level.fog.Model==1 ? "Exp" : (level.fog.Model==2 ? "Exp2" : "Linear"))); - if(level.fog.Model) - gi.dprintf("Density: %f\n",level.fog.Density); + level.current_fog.Color[0], level.current_fog.Color[1], level.current_fog.Color[2], + ((level.current_fog.Model == 1) ? "Exp" : ((level.current_fog.Model == 2) ? "Exp2" : "Linear"))); + if (level.current_fog.Model) + gi.dprintf("Density: %f\n", level.current_fog.Density); else { - gi.dprintf(" Near: %f\n",level.fog.Near); - gi.dprintf(" Far: %f\n",level.fog.Far); + gi.dprintf(" Near: %f\n", level.current_fog.Near); + gi.dprintf(" Far: %f\n", level.current_fog.Far); } } else gi.dprintf("No fogs currently active\n"); } - else if(Q_stricmp (cmd, "fog_stuff") == 0 ) + else if (Q_stricmp (cmd, "fog_stuff") == 0 ) { gi.dprintf("active_fog=%d, last_active_fog=%d\n",level.active_fog,level.last_active_fog); } - else if(Q_stricmp (cmd, "fog") == 0 ) + else if (Q_stricmp (cmd, "fog") == 0 ) { - if(parm) + if (parm) { int on; on = atoi(parm); @@ -243,9 +247,9 @@ void Cmd_Fog_f (edict_t *ent) } gi.dprintf("fog is %s\n",(level.active_fog ? "on" : "off")); } - else if(Q_stricmp (cmd, "Fog_Red") == 0 ) + else if (Q_stricmp (cmd, "Fog_Red") == 0 ) { - if(!parm) + if (!parm) gi.dprintf("%s = %f\n",cmd,fog->Color[0]); else { @@ -254,9 +258,9 @@ void Cmd_Fog_f (edict_t *ent) Fog_ConsoleFog(); } } - else if(Q_stricmp (cmd, "Fog_Grn") == 0 ) + else if (Q_stricmp (cmd, "Fog_Grn") == 0 ) { - if(!parm) + if (!parm) gi.dprintf("%s = %f\n",cmd,fog->Color[1]); else { @@ -265,9 +269,9 @@ void Cmd_Fog_f (edict_t *ent) Fog_ConsoleFog(); } } - else if(Q_stricmp (cmd, "Fog_Blu") == 0 ) + else if (Q_stricmp (cmd, "Fog_Blu") == 0 ) { - if(!parm) + if (!parm) gi.dprintf("%s = %f\n",cmd,fog->Color[2]); else { @@ -276,9 +280,9 @@ void Cmd_Fog_f (edict_t *ent) Fog_ConsoleFog(); } } - else if(Q_stricmp (cmd, "Fog_Near") == 0 ) + else if (Q_stricmp (cmd, "Fog_Near") == 0 ) { - if(!parm) + if (!parm) gi.dprintf("%s = %f\n",cmd,fog->Near); else { @@ -287,9 +291,9 @@ void Cmd_Fog_f (edict_t *ent) Fog_ConsoleFog(); } } - else if(Q_stricmp (cmd, "Fog_Far") == 0 ) + else if (Q_stricmp (cmd, "Fog_Far") == 0 ) { - if(!parm) + if (!parm) gi.dprintf("%s = %f\n",cmd,fog->Far); else { @@ -298,25 +302,25 @@ void Cmd_Fog_f (edict_t *ent) Fog_ConsoleFog(); } } - else if(Q_stricmp (cmd, "Fog_Model") == 0 ) + else if (Q_stricmp (cmd, "Fog_Model") == 0 ) { - if(!parm) + if (!parm) gi.dprintf("%s = %d\n0=Linear\n1=Exp\n2=Exp2\n",cmd,fog->Model); else { level.active_fog = level.active_target_fog = 1; //fog->Model = max(0,min(2,atoi(parm))); fog->Model = max(0,min(3,atoi(parm))); - if(fog->Model == 3) + if (fog->Model == 3) fog->GL_Model = GLModels[2]; else fog->GL_Model = GLModels[fog->Model]; Fog_ConsoleFog(); } } - else if(Q_stricmp (cmd, "Fog_Density") == 0 ) + else if (Q_stricmp (cmd, "Fog_Density") == 0 ) { - if(!parm) + if (!parm) gi.dprintf("%s = %f\n",cmd,fog->Density); else { @@ -330,17 +334,17 @@ void Cmd_Fog_f (edict_t *ent) int i; fog_t *cFog; - gi.dprintf("level.fogs=%d\n",level.fogs); - gi.dprintf("level.trigger_fogs=%d\n",level.trigger_fogs); - for (i=0; iTrigger ? "true" : "false")); + gi.dprintf("Trigger=%s\n", (cFog->Trigger ? "true" : "false")); gi.dprintf("Model=%d, Near=%g, Far=%g, Density=%g\n", cFog->Model, cFog->Near, cFog->Far, cFog->Density); - gi.dprintf("Color=%g,%g,%g\n",cFog->Color[0],cFog->Color[1],cFog->Color[2]); - gi.dprintf("Targetname=%s\n",(cFog->ent ? cFog->ent->targetname : "no ent")); + gi.dprintf("Color=%g,%g,%g\n", cFog->Color[0],cFog->Color[1],cFog->Color[2]); + gi.dprintf("Targetname=%s\n", (cFog->ent ? cFog->ent->targetname : "no ent")); } } else @@ -348,40 +352,40 @@ void Cmd_Fog_f (edict_t *ent) } /* -void SoftwareFog (void) +void SoftwareFog (edict_t *ent) { - edict_t *player = &g_edicts[1]; + if (!ent || !ent->client) // || ent->is_bot) + return; - player->client->fadein = level.framenum - 1; - player->client->fadehold = level.framenum + 2; - player->client->fadeout = 0; - player->client->fadecolor[0] = pfog->Color[0]; - player->client->fadecolor[1] = pfog->Color[1]; - player->client->fadecolor[2] = pfog->Color[2]; + ent->client->fadein = level.framenum - 1; + ent->client->fadehold = level.framenum + 2; + ent->client->fadeout = 0.0f; + ent->client->fadecolor[0] = pfog->Color[0]; + ent->client->fadecolor[1] = pfog->Color[1]; + ent->client->fadecolor[2] = pfog->Color[2]; - if(pfog->Model == 0) - player->client->fadealpha = pfog->Far/256.; - else if(pfog->Model == 1) - player->client->fadealpha = pfog->Density/30; + if (pfog->Model == 0) + ent->client->fadealpha = pfog->Far / 256.0f; + else if (pfog->Model == 1) + ent->client->fadealpha = pfog->Density / 30.0f; else - player->client->fadealpha = pfog->Density/15; + ent->client->fadealpha = pfog->Density / 15.0f; - if(player->client->fadealpha > 0.9) - player->client->fadealpha = 0.9; + if (ent->client->fadealpha > 0.9f) + ent->client->fadealpha = 0.9f; last_software_frame = level.framenum; - } */ -void GLFog (void) +void GLFog (edict_t *ent) { #ifdef KMQUAKE2_ENGINE_MOD // engine fog - edict_t *player_ent = &g_edicts[1]; +// edict_t *player_ent = &g_edicts[1]; int fog_model, fog_density, fog_near, fog_far, fog_color[3]; - if (!player_ent->client || player_ent->is_bot) + if (!ent || !ent->client || ent->is_bot) return; if (pfog->GL_Model == GL_EXP) @@ -412,12 +416,12 @@ void GLFog (void) gi.WriteByte (1); // enable message gi.WriteByte (fog_model); // model 0, 1, or 2 gi.WriteByte (fog_density); // density 1-100 - gi.WriteShort (fog_near); // near >0, fog_near-64, < 5000 + gi.WriteShort (fog_near); // near >0, < fog_far + gi.WriteShort (fog_far); // far >fog_near-64, < 10000 gi.WriteByte (fog_color[0]); // red 0-255 gi.WriteByte (fog_color[1]); // green 0-255 gi.WriteByte (fog_color[2]); // blue 0-255 - gi.unicast (player_ent, true); + gi.unicast (ent, true); // write to last fog state last_fog_model = fog_model; @@ -429,7 +433,7 @@ void GLFog (void) #else // old sever-side fog GLfloat fogColor[4]; - if(!hOpenGL) return; + if (!hOpenGL) return; fogColor[0] = pfog->Color[0]; fogColor[1] = pfog->Color[1]; fogColor[2] = pfog->Color[2]; @@ -438,7 +442,7 @@ void GLFog (void) GL_glClearColor ( fogColor[0], fogColor[1], fogColor[2], fogColor[3]); // Clear the background color to the fog color GL_glFogi (GL_FOG_MODE, pfog->GL_Model); GL_glFogfv (GL_FOG_COLOR, fogColor); - if(pfog->GL_Model == GL_LINEAR) + if (pfog->GL_Model == GL_LINEAR) { GL_glFogf (GL_FOG_START, pfog->Near); GL_glFogf (GL_FOG_END, pfog->Far); @@ -456,16 +460,16 @@ void trig_fog_fade (edict_t *self) float frames; int index; - if(!InTriggerFog) + if (!InTriggerFog) { self->nextthink = 0; return; } - if(level.framenum <= self->goal_frame) + if (level.framenum <= self->goal_frame) { index = self->fog_index-1; frames = self->goal_frame - level.framenum + 1; - if(trig_fade_fog.Model == 0) + if (trig_fade_fog.Model == 0) { trig_fade_fog.Near += (gfogs[index].Near - trig_fade_fog.Near)/frames; trig_fade_fog.Far += (gfogs[index].Far - trig_fade_fog.Far )/frames; @@ -495,11 +499,11 @@ void init_trigger_fog_delay (edict_t *self) // scan for other trigger_fog's that are currently "thinking", iow // the trigger_fog has a delay and is ramping. If found, stop the ramp for those fogs - for(i=1, e=g_edicts+i; iinuse) continue; - if(e == self) continue; - if(e->think == trig_fog_fade || e->think == fog_fade) + if (!e->inuse) continue; + if (e == self) continue; + if (e->think == trig_fog_fade || e->think == fog_fade) { e->think = NULL; e->nextthink = 0; @@ -508,15 +512,15 @@ void init_trigger_fog_delay (edict_t *self) } self->spawnflags |= FOG_ON; - if(!level.active_fog) + if (!level.active_fog) { // Fog isn't currently on - memcpy(&level.fog,&gfogs[index],sizeof(fog_t)); - level.fog.Near = 4999.; - level.fog.Far = 5000.; - level.fog.Density = 0.0; - level.fog.Density1 = 0.0; - level.fog.Density2 = 0.0; + memcpy(&level.current_fog, &gfogs[index], sizeof(fog_t)); + level.current_fog.Near = 4999.0f; + level.current_fog.Far = 5000.0f; + level.current_fog.Density = 0.0f; + level.current_fog.Density1 = 0.0f; + level.current_fog.Density2 = 0.0f; } VectorCopy(self->fog_color,gfogs[index].Color); gfogs[index].Near = self->fog_near; @@ -527,14 +531,14 @@ void init_trigger_fog_delay (edict_t *self) self->goal_frame = level.framenum + self->delay*10 + 1; self->think = trig_fog_fade; self->nextthink = level.time + FRAMETIME; - memcpy(&trig_fade_fog,&level.fog,sizeof(fog_t)); + memcpy(&trig_fade_fog, &level.current_fog, sizeof(fog_t)); level.active_fog = self->fog_index; } -void Fog (edict_t *ent) //vec3_t viewpoint) +void Fog (edict_t *ent) { edict_t *triggerfog; - edict_t *player = ent; //&g_edicts[1]; +// edict_t *player = ent; //&g_edicts[1]; vec3_t viewpoint; if (!gl_driver || !vid_ref) @@ -543,13 +547,13 @@ void Fog (edict_t *ent) //vec3_t viewpoint) if (deathmatch->value || coop->value) return; - if (!player->client || player->is_bot) + if (!ent || !ent->client || ent->is_bot) return; - VectorCopy(player->s.origin, viewpoint); + VectorCopy(ent->s.origin, viewpoint); viewpoint[2] += ent->viewheight; - if(Q_stricmp(vid_ref->string,"gl")) + if (Q_stricmp(vid_ref->string,"gl")) { last_software_frame = level.framenum; level.active_fog = 0; @@ -557,54 +561,54 @@ void Fog (edict_t *ent) //vec3_t viewpoint) } InTriggerFog = false; - if(level.trigger_fogs) + if (level.num_trigger_fogs) { int i; int trigger; - trigger=0; - for(i=1; iinuse) continue; - if(!(gfogs[i].ent->spawnflags & FOG_ON)) continue; - if(viewpoint[0] < gfogs[i].ent->absmin[0]) continue; - if(viewpoint[0] > gfogs[i].ent->absmax[0]) continue; - if(viewpoint[1] < gfogs[i].ent->absmin[1]) continue; - if(viewpoint[1] > gfogs[i].ent->absmax[1]) continue; - if(viewpoint[2] < gfogs[i].ent->absmin[2]) continue; - if(viewpoint[2] > gfogs[i].ent->absmax[2]) continue; + if (!gfogs[i].Trigger) continue; + if (!gfogs[i].ent->inuse) continue; + if (!(gfogs[i].ent->spawnflags & FOG_ON)) continue; + if (viewpoint[0] < gfogs[i].ent->absmin[0]) continue; + if (viewpoint[0] > gfogs[i].ent->absmax[0]) continue; + if (viewpoint[1] < gfogs[i].ent->absmin[1]) continue; + if (viewpoint[1] > gfogs[i].ent->absmax[1]) continue; + if (viewpoint[2] < gfogs[i].ent->absmin[2]) continue; + if (viewpoint[2] > gfogs[i].ent->absmax[2]) continue; trigger = i; break; } - if(trigger) + if (trigger) { InTriggerFog = true; triggerfog = gfogs[trigger].ent; - if(level.last_active_fog != trigger+1) + if (level.last_active_fog != trigger+1) { - if(triggerfog->delay) + if (triggerfog->delay) init_trigger_fog_delay(triggerfog); else - memcpy(&level.fog,&gfogs[trigger],sizeof(fog_t)); + memcpy(&level.current_fog, &gfogs[trigger], sizeof(fog_t)); level.active_fog = trigger+1; } - else if(triggerfog->delay) - memcpy(&level.fog,&trig_fade_fog,sizeof(fog_t)); + else if (triggerfog->delay) + memcpy(&level.current_fog, &trig_fade_fog, sizeof(fog_t)); } else { InTriggerFog = false; level.active_fog = level.active_target_fog; // if we are just coming out of a trigger_fog, force - // level.fog to last active target_fog values - if(level.active_fog && level.last_active_fog && gfogs[level.last_active_fog-1].Trigger) + // level.current_fog to last active target_fog values + if (level.active_fog && level.last_active_fog && gfogs[level.last_active_fog-1].Trigger) { edict_t *ent = gfogs[level.active_fog-1].ent; - if(ent && (ent->think == fog_fade)) + if (ent && (ent->think == fog_fade)) ent->think(ent); else - memcpy(&level.fog,&gfogs[level.active_fog-1],sizeof(fog_t)); + memcpy(&level.current_fog, &gfogs[level.active_fog-1], sizeof(fog_t)); } } } @@ -612,62 +616,59 @@ void Fog (edict_t *ent) //vec3_t viewpoint) if (!level.active_fog) { if (level.last_active_fog) - Fog_Off (false); + Fog_Off (ent); level.last_active_fog = 0; return; } - pfog = &level.fog; - if((pfog->Density1 != pfog->Density2) && (game.maxclients == 1) && (pfog->Model)) + pfog = &level.current_fog; + if ((pfog->Density1 != pfog->Density2) && (game.maxclients == 1) && (pfog->Model)) { float density; float dp; vec3_t vp; - AngleVectors(player->client->ps.viewangles,vp,0,0); + AngleVectors(ent->client->ps.viewangles,vp,0,0); dp = DotProduct(pfog->Dir,vp) + 1.0; density = ((pfog->Density1*dp) + (pfog->Density2*(2.0-dp)))/2.; - if(pfog->Density != density) + if (pfog->Density != density) { pfog->Density = density; } } - GLFog(); + GLFog (ent); level.last_active_fog = level.active_fog; } -void Fog_Off (qboolean gameShutdown) +void Fog_Off (edict_t *ent) { if (deathmatch->value || coop->value) return; -#ifdef KMQUAKE2_ENGINE_MOD // engine fog // If game is shutting down, g_edicts will likely be invalid // and the client will clear the fog automatically - if (gameShutdown) +// if (gameShutdown) +// return; + + if (!ent || !ent->client || ent->is_bot) return; - { - edict_t *player_ent = &g_edicts[1]; +#ifdef KMQUAKE2_ENGINE_MOD // engine fog - if (!player_ent->client || player_ent->is_bot) - return; + gi.WriteByte (svc_fog); // svc_fog = 21 + gi.WriteByte (0); // disable message, remaining paramaters are ignored + gi.WriteByte (0); // 0, 1, or 2 + gi.WriteByte (0); // 1-100 + gi.WriteShort (0); // >0, < fog_far + gi.WriteShort (0); // >fog_near-64, < 10000 + gi.WriteByte (0); // 0-255 + gi.WriteByte (0); // 0-255 + gi.WriteByte (0); // 0-255 + gi.unicast (ent, true); - gi.WriteByte (svc_fog); // svc_fog = 21 - gi.WriteByte (0); // disable message, remaining paramaters are ignored - gi.WriteByte (0); // 0, 1, or 2 - gi.WriteByte (0); // 1-100 - gi.WriteShort (0); // >0, fog_near-64, < 5000 - gi.WriteByte (0); // 0-255 - gi.WriteByte (0); // 0-255 - gi.WriteByte (0); // 0-255 - gi.unicast (player_ent, true); - - // write to last fog state - last_fog_model = last_fog_density = last_fog_near = last_fog_far = 0; - VectorSet (last_fog_color, 255, 255, 255); - } + // write to last fog state + last_fog_model = last_fog_density = last_fog_near = last_fog_far = 0; + VectorSet (last_fog_color, 255, 255, 255); #else // old sever-side fog @@ -675,7 +676,27 @@ void Fog_Off (qboolean gameShutdown) { if (!strcmp(vid_ref->string,"gl")) { - if (hOpenGL) GL_glDisable (GL_FOG); + if (hOpenGL) + GL_glDisable (GL_FOG); + } + else + { + ent->client->fadein = 0; + } + } + +#endif // KMQUAKE2_ENGINE_MOD +} + +void Fog_Off_Global (void) +{ +#ifndef KMQUAKE2_ENGINE_MOD // old sever-side fog + if (gl_driver && vid_ref) + { + if (!strcmp(vid_ref->string, "gl")) + { + if (hOpenGL) + GL_glDisable (GL_FOG); } else { @@ -685,7 +706,6 @@ void Fog_Off (qboolean gameShutdown) player->client->fadein = 0; } } - #endif // KMQUAKE2_ENGINE_MOD } @@ -734,11 +754,11 @@ void fog_fade (edict_t *self) float frames; int index; - if(level.framenum <= self->goal_frame) + if (level.framenum <= self->goal_frame) { index = self->fog_index-1; frames = self->goal_frame - level.framenum + 1; - if(fade_fog.Model == 0) + if (fade_fog.Model == 0) { fade_fog.Near += (gfogs[index].Near - fade_fog.Near)/frames; fade_fog.Far += (gfogs[index].Far - fade_fog.Far )/frames; @@ -754,14 +774,14 @@ void fog_fade (edict_t *self) fade_fog.Color[2] += (gfogs[index].Color[2] - fade_fog.Color[2])/frames; fade_fog.GL_Model = GLModels[fade_fog.Model]; self->nextthink = level.time + FRAMETIME; - if(!InTriggerFog) - memcpy(&level.fog,&fade_fog,sizeof(fog_t)); + if (!InTriggerFog) + memcpy(&level.current_fog, &fade_fog, sizeof(fog_t)); gi.linkentity(self); } else { -// if(!(self->spawnflags & FOG_ON)) - if(self->spawnflags & FOG_TURNOFF) + // if (!(self->spawnflags & FOG_ON)) + if (self->spawnflags & FOG_TURNOFF) level.active_fog = level.active_target_fog = 0; } } @@ -795,14 +815,19 @@ void target_fog_use (edict_t *self, edict_t *other, edict_t *activator) int index; edict_t *e; + if (!self) + return; +// if (!activator || !activator->client) +// return; + self->count--; - if(self->count == 0) + if (self->count == 0) { self->think = G_FreeEdict; self->nextthink = level.time + self->delay + 1; } - if((self->spawnflags & FOG_ON) && (self->spawnflags & FOG_TOGGLE)) + if ((self->spawnflags & FOG_ON) && (self->spawnflags & FOG_TOGGLE)) { self->spawnflags &= ~FOG_ON; return; @@ -816,50 +841,50 @@ void target_fog_use (edict_t *self, edict_t *other, edict_t *activator) // scan for other target_fog's that are currently "thinking", iow // the target_fog has a delay and is ramping. If found, stop the ramp for those fogs - for(i=1, e=g_edicts+i; iinuse) continue; - if(e->think == fog_fade) + if (!e->inuse) continue; + if (e->think == fog_fade) { e->nextthink = 0; gi.linkentity(e); } } - if(self->spawnflags & FOG_TURNOFF) + if (self->spawnflags & FOG_TURNOFF) { // Fog is "turn off" only - if( self->delay && level.active_fog ) + if ( self->delay && level.active_fog ) { - gfogs[index].Far = 5000.0; - gfogs[index].Near = 4999.0; - gfogs[index].Density = 0.0; - gfogs[index].Density1 = 0.0; - gfogs[index].Density2 = 0.0; - VectorCopy(level.fog.Color,gfogs[index].Color); + gfogs[index].Far = 5000.0f; + gfogs[index].Near = 4999.0f; + gfogs[index].Density = 0.0f; + gfogs[index].Density1 = 0.0f; + gfogs[index].Density2 = 0.0f; + VectorCopy(level.current_fog.Color,gfogs[index].Color); self->goal_frame = level.framenum + self->delay*10 + 1; self->think = fog_fade; self->nextthink = level.time + FRAMETIME; level.active_fog = level.active_target_fog = self->fog_index; - memcpy(&fade_fog,&level.fog,sizeof(fog_t)); + memcpy(&fade_fog, &level.current_fog, sizeof(fog_t)); } else level.active_fog = level.active_target_fog = 0; } else { - if(self->delay) + if (self->delay) { - if(!level.active_fog) + if (!level.active_fog) { // Fog isn't currently on - memcpy(&level.fog,&gfogs[index],sizeof(fog_t)); - level.fog.Near = 4999.; - level.fog.Far = 5000.; - level.fog.Density = 0.0; - level.fog.Density1 = 0.0; - level.fog.Density2 = 0.0; + memcpy(&level.current_fog, &gfogs[index], sizeof(fog_t)); + level.current_fog.Near = 4999.0f; + level.current_fog.Far = 5000.0f; + level.current_fog.Density = 0.0f; + level.current_fog.Density1 = 0.0f; + level.current_fog.Density2 = 0.0f; } VectorCopy(self->fog_color,gfogs[index].Color); gfogs[index].Near = self->fog_near; @@ -870,9 +895,10 @@ void target_fog_use (edict_t *self, edict_t *other, edict_t *activator) self->goal_frame = level.framenum + self->delay*10 + 1; self->think = fog_fade; self->nextthink = level.time + FRAMETIME; - memcpy(&fade_fog,&level.fog,sizeof(fog_t)); - } else { - memcpy(&level.fog,&gfogs[index],sizeof(fog_t)); + memcpy(&fade_fog, &level.current_fog, sizeof(fog_t)); + } + else { + memcpy(&level.current_fog, &gfogs[index], sizeof(fog_t)); } level.active_fog = level.active_target_fog = self->fog_index; } @@ -895,26 +921,28 @@ void SP_target_fog (edict_t *self) self->class_id = ENTITY_TARGET_FOG; - if(!level.fogs) level.fogs = 1; // 1st fog reserved for console commands + if (!level.num_fogs) + level.num_fogs = 1; // 1st fog reserved for console commands - if(level.fogs >= MAX_FOGS) + if (level.num_fogs >= MAX_FOGS) { gi.dprintf("Maximum number of fogs exceeded!\n"); G_FreeEdict(self); return; } - if( self->delay < 0.) - self->delay = 0.; + if (self->delay < 0.0f) + self->delay = 0.0f; - self->fog_index = level.fogs+1; - fog = &gfogs[level.fogs]; + self->fog_index = level.num_fogs+1; + fog = &gfogs[level.num_fogs]; fog->Trigger = false; - fog->Model = self->fog_model; - if(fog->Model < 0 || fog->Model > 2) fog->Model = 0; + fog->Model = self->fog_model; + if (fog->Model < 0 || fog->Model > 2) + fog->Model = 0; fog->GL_Model = GLModels[fog->Model]; VectorCopy(self->fog_color,fog->Color); - if(self->spawnflags & FOG_TURNOFF) + if (self->spawnflags & FOG_TURNOFF) { fog->Near = 4999; fog->Far = 5000; @@ -928,22 +956,22 @@ void SP_target_fog (edict_t *self) fog->Far = self->fog_far; fog->Density = self->fog_density; fog->Density1 = self->fog_density; - if(self->density == 0.) + if (self->density == 0.0f) self->density = self->fog_density; - else if(self->density < 0.) - self->density = 0.; - fog->Density2= self->density; + else if (self->density < 0.0f) + self->density = 0.0f; + fog->Density2 = self->density; } - AngleVectors(self->s.angles,fog->Dir,0,0); + AngleVectors(self->s.angles, fog->Dir, 0, 0); fog->ent = self; - level.fogs++; + level.num_fogs++; self->use = target_fog_use; gi.linkentity(self); - if(self->spawnflags & FOG_ON) + if (self->spawnflags & FOG_ON) { self->spawnflags &= ~FOG_ON; - target_fog_use(self,NULL,NULL); + target_fog_use(self, NULL, NULL); } } @@ -966,11 +994,11 @@ Fog field void trigger_fog_use (edict_t *self, edict_t *other, edict_t *activator) { - if((self->spawnflags & FOG_ON) && (self->spawnflags & FOG_TOGGLE)) + if ((self->spawnflags & FOG_ON) && (self->spawnflags & FOG_TOGGLE)) { self->spawnflags &= ~FOG_ON; self->count--; - if(self->count == 0) + if (self->count == 0) { self->think = G_FreeEdict; self->nextthink = level.time + FRAMETIME; @@ -986,12 +1014,12 @@ void SP_trigger_fog (edict_t *self) { fog_t *fog; - if( !allow_fog->value ) + if (!allow_fog->value) { G_FreeEdict(self); return; } - if(deathmatch->value || coop->value) + if (deathmatch->value || coop->value) { G_FreeEdict(self); return; @@ -999,29 +1027,31 @@ void SP_trigger_fog (edict_t *self) self->class_id = ENTITY_TRIGGER_FOG; - if(!level.fogs) level.fogs = 1; // 1st fog reserved for console commands + if (!level.num_fogs) + level.num_fogs = 1; // 1st fog reserved for console commands - if(level.fogs >= MAX_FOGS) + if (level.num_fogs >= MAX_FOGS) { gi.dprintf("Maximum number of fogs exceeded!\n"); G_FreeEdict(self); return; } - self->fog_index = level.fogs+1; - fog = &gfogs[level.fogs]; + self->fog_index = level.num_fogs+1; + fog = &gfogs[level.num_fogs]; fog->Trigger = true; fog->Model = self->fog_model; - if(fog->Model < 0 || fog->Model > 2) fog->Model = 0; + if (( fog->Model < 0) || (fog->Model > 2) ) + fog->Model = 0; fog->GL_Model = GLModels[fog->Model]; VectorCopy(self->fog_color,fog->Color); - if(self->spawnflags & FOG_TURNOFF) + if (self->spawnflags & FOG_TURNOFF) { - fog->Near = 4999; - fog->Far = 5000; - fog->Density = 0; - fog->Density1 = 0; - fog->Density2 = 0; + fog->Near = 4999.0f; + fog->Far = 5000.0f; + fog->Density = 0.0f; + fog->Density1 = 0.0f; + fog->Density2 = 0.0f; } else { @@ -1029,20 +1059,20 @@ void SP_trigger_fog (edict_t *self) fog->Far = self->fog_far; fog->Density = self->fog_density; fog->Density1 = self->fog_density; - if(self->density == 0.) + if (self->density == 0.0f) self->density = self->fog_density; - else if(self->density < 0.) - self->density = 0.; - fog->Density2= self->density; + else if (self->density < 0.0f) + self->density = 0.0f; + fog->Density2 = self->density; } - if(!(self->spawnflags & FOG_STARTOFF)) + if (!(self->spawnflags & FOG_STARTOFF)) self->spawnflags |= FOG_ON; - AngleVectors(self->s.angles,fog->Dir,0,0); + AngleVectors(self->s.angles, fog->Dir, 0, 0); VectorClear(self->s.angles); fog->ent = self; - level.fogs++; - level.trigger_fogs++; + level.num_fogs++; + level.num_trigger_fogs++; self->movetype = MOVETYPE_NONE; self->svflags |= SVF_NOCLIENT; self->solid = SOLID_NOT; @@ -1074,12 +1104,12 @@ void SP_trigger_fog_bbox (edict_t *self) { fog_t *fog; - if( !allow_fog->value ) + if (!allow_fog->value) { G_FreeEdict(self); return; } - if(deathmatch->value || coop->value) + if (deathmatch->value || coop->value) { G_FreeEdict(self); return; @@ -1087,29 +1117,31 @@ void SP_trigger_fog_bbox (edict_t *self) self->class_id = ENTITY_TRIGGER_FOG; - if(!level.fogs) level.fogs = 1; // 1st fog reserved for console commands + if (!level.num_fogs) + level.num_fogs = 1; // 1st fog reserved for console commands - if(level.fogs >= MAX_FOGS) + if (level.num_fogs >= MAX_FOGS) { gi.dprintf("Maximum number of fogs exceeded!\n"); G_FreeEdict(self); return; } - self->fog_index = level.fogs+1; - fog = &gfogs[level.fogs]; + self->fog_index = level.num_fogs+1; + fog = &gfogs[level.num_fogs]; fog->Trigger = true; fog->Model = self->fog_model; - if(fog->Model < 0 || fog->Model > 2) fog->Model = 0; + if (fog->Model < 0 || fog->Model > 2) + fog->Model = 0; fog->GL_Model = GLModels[fog->Model]; VectorCopy(self->fog_color,fog->Color); - if(self->spawnflags & FOG_TURNOFF) + if (self->spawnflags & FOG_TURNOFF) { - fog->Near = 4999; - fog->Far = 5000; - fog->Density = 0; - fog->Density1 = 0; - fog->Density2 = 0; + fog->Near = 4999.0f; + fog->Far = 5000.0f; + fog->Density = 0.0f; + fog->Density1 = 0.0f; + fog->Density2 = 0.0f; } else { @@ -1117,20 +1149,20 @@ void SP_trigger_fog_bbox (edict_t *self) fog->Far = self->fog_far; fog->Density = self->fog_density; fog->Density1 = self->fog_density; - if(self->density == 0.) + if (self->density == 0.0f) self->density = self->fog_density; - else if(self->density < 0.) - self->density = 0.; - fog->Density2= self->density; + else if (self->density < 0.0f) + self->density = 0.0f; + fog->Density2 = self->density; } - if(!(self->spawnflags & FOG_STARTOFF)) + if (!(self->spawnflags & FOG_STARTOFF)) self->spawnflags |= FOG_ON; - AngleVectors(self->s.angles,fog->Dir,0,0); + AngleVectors(self->s.angles, fog->Dir, 0, 0); VectorClear(self->s.angles); - fog->ent = self; - level.fogs++; - level.trigger_fogs++; + fog->ent = self; + level.num_fogs++; + level.num_trigger_fogs++; self->movetype = MOVETYPE_NONE; self->svflags |= SVF_NOCLIENT; self->solid = SOLID_NOT; diff --git a/game/g_local.h b/game/g_local.h index e195cb6..bd15600 100644 --- a/game/g_local.h +++ b/game/g_local.h @@ -440,12 +440,12 @@ typedef struct int disguise_violation_framenum; // Lazarus - int fogs; - int trigger_fogs; + int num_fogs; + int num_trigger_fogs; int active_target_fog; int active_fog; int last_active_fog; - fog_t fog; + fog_t current_fog; int flashlight_cost; // cost/10 seconds for flashlight int mud_puddles; int num_3D_sounds; @@ -938,6 +938,7 @@ void cleanupHealTarget (edict_t *ent); #define DEFAULT_DEATHMATCH_SHOTGUN_COUNT 12 #define DEFAULT_SHOTGUN_COUNT 12 #define DEFAULT_SSHOTGUN_COUNT 20 + // // g_cmds.c // @@ -948,22 +949,26 @@ void Use_Flashlight(edict_t *ent,gitem_t *item); void SetLazarusCrosshair (edict_t *ent); void SetSensitivities(edict_t *ent,qboolean reset); void ShiftItem(edict_t *ent, int direction); + // // g_crane.c // void G_FindCraneParts(); void crane_control_action(edict_t *crane, edict_t *activator, vec3_t point); void Moving_Speaker_Think(edict_t *ent); + // // g_fog.c // -#define MAX_FOGS 16 +#define MAX_FOGS 64 // was 16 extern fog_t gfogs[MAX_FOGS]; void Cmd_Fog_f (edict_t *ent); void Fog_Init (void); -void Fog (edict_t *ent); //vec3_t viewpoint); -void Fog_Off (qboolean gameShutdown); +void Fog (edict_t *ent); +void Fog_Off (edict_t *ent); +void Fog_Off_Global (void); void Fog_SetFogParms (void); + // // g_func.c // diff --git a/game/g_main.c b/game/g_main.c index 0dd42d1..5a12f55 100644 --- a/game/g_main.c +++ b/game/g_main.c @@ -164,8 +164,10 @@ void ShutdownGame (void) //gi.cvar_forceset("gl_clear", va("%d", lazarus_gl_clear->value)); } // Lazarus: Turn off fog if it's on - if (!dedicated->value) - Fog_Off (true); + if (!dedicated->value) { + // Fog_Off (true); + Fog_Off_Global (); + } gi.FreeTags (TAG_LEVEL); gi.FreeTags (TAG_GAME); diff --git a/game/p_client.c b/game/p_client.c index cb63153..70c21b6 100644 --- a/game/p_client.c +++ b/game/p_client.c @@ -2090,7 +2090,7 @@ void ClientBegin (edict_t *ent) return; } - Fog_Off (false); + Fog_Off (ent); stuffcmd(ent,"alias +zoomin zoomin;alias -zoomin zoominstop\n"); stuffcmd(ent,"alias +zoomout zoomout;alias -zoomout zoomoutstop\n"); diff --git a/game/q_shared.h b/game/q_shared.h index e37f531..8b4db29 100644 --- a/game/q_shared.h +++ b/game/q_shared.h @@ -1500,7 +1500,7 @@ typedef enum EV_WADE, // wading or treading water EV_WADE_MUD, // wading in mud EV_CLIMB_LADDER, //climbing ladder - EV_PLAYER_TELEPORT_Q1 // Q1 teleport, sounds in rogue pak0.pak + EV_PLAYER_TELEPORT2 // Q1-style teleport, sounds in rogue pak0.pak // end Knightmare } entity_event_t; diff --git a/kmquake2_changelog.txt b/kmquake2_changelog.txt index c195cff..215f6db 100644 --- a/kmquake2_changelog.txt +++ b/kmquake2_changelog.txt @@ -13,6 +13,8 @@ Changes as of v0.20 update 8: - Added Windows DPI scaling detection from Yamagi Quake2. +- Added support for quake2:// URLs. + - Added cel shading support. Uses cvars r_celshading to enable, and r_celshading_width for line width (1-10). - Now compresses .sav and .sv2 savegame files into .savz files. It will still read savegames from earlier diff --git a/missionpack/g_ai.c b/missionpack/g_ai.c index 62e3527..7edcb79 100644 --- a/missionpack/g_ai.c +++ b/missionpack/g_ai.c @@ -280,9 +280,15 @@ void ai_charge (edict_t *self, float dist) // PMM - made AI_MANUAL_STEERING affect things differently here .. they turn, but // don't set the ideal_yaw + // Zaero + if (self->monsterinfo.aiflags2 & AI2_ONESHOTTARGET) + { + VectorSubtract (self->monsterinfo.shottarget, self->s.origin, v); + } + // This is put in there so monsters won't move towards the origin after killing // a tesla. This could be problematic, so keep an eye on it. - if(!self->enemy || !self->enemy->inuse) //PGM + if (!self->enemy || !self->enemy->inuse) //PGM return; //PGM // PMM - save blindfire target @@ -431,17 +437,17 @@ qboolean visible (edict_t *self, edict_t *other) if ( (trace.fraction == 1.0) || (trace.ent == other)) { - if( (level.active_fog) && (self->svflags & SVF_MONSTER) ) + if ( (level.active_fog) && (self->svflags & SVF_MONSTER) ) { fog_t *pfog; float r; float dw; vec3_t v; - pfog = &level.fog; + pfog = &level.current_fog; VectorSubtract(spot2,spot1,v); r = VectorLength(v); - switch(pfog->Model) + switch (pfog->Model) { case 1: dw = pfog->Density/10000. * r; @@ -452,17 +458,17 @@ qboolean visible (edict_t *self, edict_t *other) self->monsterinfo.visibility = exp( -dw*dw ); break; default: - if((r < pfog->Near) || (pfog->Near == pfog->Far)) + if ((r < pfog->Near) || (pfog->Near == pfog->Far)) self->monsterinfo.visibility = 1.0; - else if(r > pfog->Far) + else if (r > pfog->Far) self->monsterinfo.visibility = 0.0; else self->monsterinfo.visibility = 1.0 - (r - pfog->Near)/(pfog->Far - pfog->Near); break; } -// if(developer->value) -// gi.dprintf("r=%g, vis=%g\n",r,self->monsterinfo.visibility); - if(self->monsterinfo.visibility < 0.05) + // if (developer->value) + // gi.dprintf("r=%g, vis=%g\n",r,self->monsterinfo.visibility); + if (self->monsterinfo.visibility < 0.05) return false; else return true; @@ -674,7 +680,7 @@ qboolean FindTarget (edict_t *self) edict_t *reflection = NULL; edict_t *self_reflection = NULL; -// if(self->monsterinfo.aiflags & (AI_CHASE_THING /*| AI_HINT_TEST*/)) +// if ((self->monsterinfo.aiflags & AI_CHASE_THING) || (self->monsterinfo.aiflags2 & AI2_HINT_TEST) ) // return false; if (self->monsterinfo.aiflags & AI_GOOD_GUY) diff --git a/missionpack/g_cmds.c b/missionpack/g_cmds.c index 552897a..908e343 100644 --- a/missionpack/g_cmds.c +++ b/missionpack/g_cmds.c @@ -149,6 +149,7 @@ void ValidateSelectedItem (edict_t *ent) static void Cmd_Give_Usage (edict_t *ent, char *parm1) { gi.cprintf (ent, PRINT_HIGH, "usage: give %s {xatrix | rogue | neither | both}\n", parm1); +// gi.cprintf (ent, PRINT_HIGH, "usage: give %s {xatrix | rogue | zaero | neither | both}\n", parm1); } qboolean Cmd_Give_ParseFlags (edict_t *ent, char *parm1, int *flags) @@ -166,6 +167,8 @@ qboolean Cmd_Give_ParseFlags (edict_t *ent, char *parm1, int *flags) *flags |= 4; else if (Q_stricmp(gi.argv(2), "both") == 0) *flags |= 6; +// else if (Q_stricmp(gi.argv(2), "zaero") == 0) +// *flags |= 8; else if (Q_stricmp(gi.argv(2), "neither")) { Cmd_Give_Usage (ent, parm1); return false; @@ -196,7 +199,7 @@ void Cmd_Give_f (edict_t *ent) return; } - //Knightmare- override ammo pickup values with cvars + // Knightmare- override ammo pickup values with cvars SetAmmoPickupValues (); name = gi.args(); @@ -251,6 +254,8 @@ void Cmd_Give_f (edict_t *ent) continue; if ( (it->flags & IT_ROGUE) && !(give_flags & 4) ) continue; + if ( (it->flags & IT_ZAERO) && !(give_flags & 8) ) + continue; ent->client->pers.inventory[i] += 1; } if (!give_all) @@ -271,6 +276,8 @@ void Cmd_Give_f (edict_t *ent) continue; if ( (it->flags & IT_ROGUE) && !(give_flags & 4) ) continue; + if ( (it->flags & IT_ZAERO) && !(give_flags & 8) ) + continue; if (it->classname && !Q_stricmp(it->classname,"ammo_fuel") && !developer->value) continue; Add_Ammo (ent, it, 1000); @@ -328,6 +335,8 @@ void Cmd_Give_f (edict_t *ent) continue; if ( (it->flags & IT_ROGUE) && !(give_flags & 4) ) continue; + if ( (it->flags & IT_ZAERO) && !(give_flags & 8) ) + continue; if (it->classname && !Q_stricmp(it->classname,"item_jetpack") && !developer->value) continue; if (it->classname && !Q_stricmp(it->classname,"item_flashlight") && !developer->value) diff --git a/missionpack/g_combat.c b/missionpack/g_combat.c index f080e7d..6f0362f 100644 --- a/missionpack/g_combat.c +++ b/missionpack/g_combat.c @@ -114,8 +114,8 @@ void Killed (edict_t *targ, edict_t *inflictor, edict_t *attacker, int damage, v if ((targ->svflags & SVF_MONSTER) && (targ->deadflag != DEAD_DEAD)) { // targ->svflags |= SVF_DEADMONSTER; // now treat as a different content type - //ROGUE - free up slot for spawned monster if it's spawned - //if (targ->monsterinfo.aiflags & AI_SPAWNED_CARRIER) + // ROGUE - free up slot for spawned monster if it's spawned + // if (targ->monsterinfo.aiflags & AI_SPAWNED_CARRIER) if (targ->monsterinfo.monsterflags & MFL_SPAWNED_CARRIER) { if (targ->monsterinfo.commander && targ->monsterinfo.commander->inuse && @@ -126,7 +126,7 @@ void Killed (edict_t *targ, edict_t *inflictor, edict_t *attacker, int damage, v // gi.dprintf ("g_combat: freeing up carrier slot - %d left\n", targ->monsterinfo.commander->monsterinfo.monster_slots); } } - //if (targ->monsterinfo.aiflags & AI_SPAWNED_MEDIC_C) + // if (targ->monsterinfo.aiflags & AI_SPAWNED_MEDIC_C) if (targ->monsterinfo.monsterflags & MFL_SPAWNED_MEDIC_C) { if (targ->monsterinfo.commander) @@ -145,7 +145,7 @@ void Killed (edict_t *targ, edict_t *inflictor, edict_t *attacker, int damage, v // gi.dprintf ("My commander is GONE\n"); } - //if (targ->monsterinfo.aiflags & AI_SPAWNED_WIDOW) + // if (targ->monsterinfo.aiflags & AI_SPAWNED_WIDOW) if (targ->monsterinfo.monsterflags & MFL_SPAWNED_WIDOW) { // need to check this because we can have variable numbers of coop players @@ -159,7 +159,7 @@ void Killed (edict_t *targ, edict_t *inflictor, edict_t *attacker, int damage, v } } //Rogue - //if (!(targ->monsterinfo.aiflags & AI_GOOD_GUY) && !(targ->monsterinfo.aiflags & AI_DO_NOT_COUNT)) + // if (!(targ->monsterinfo.aiflags & AI_GOOD_GUY) && !(targ->monsterinfo.aiflags & AI_DO_NOT_COUNT)) if (!(targ->monsterinfo.aiflags & AI_GOOD_GUY) && !(targ->monsterinfo.monsterflags & MFL_DO_NOT_COUNT)) { level.killed_monsters++; @@ -415,7 +415,7 @@ void CallMyFriends (edict_t *targ, edict_t *attacker) } } else if( !(targ->svflags & SVF_MONSTER) || !(attacker->svflags & SVF_MONSTER) || - (targ->monsterinfo.moreaiflags & AI_FREEFORALL) || + (targ->monsterinfo.aiflags2 & AI2_FREEFORALL) || ((targ->monsterinfo.aiflags & AI_GOOD_GUY) != (attacker->monsterinfo.aiflags & AI_GOOD_GUY)) ) { // Either target is not a monster, or attacker is not a monster, or @@ -908,7 +908,7 @@ void T_Damage (edict_t *in_targ, edict_t *inflictor, edict_t *in_attacker, vec3_ // If targ is a fake player for the real player viewing camera, get that player // out of the camera and do the damage to him - if (!Q_stricmp(targ->classname,"camplayer")) + if (!Q_stricmp(targ->classname, "camplayer")) { if (targ->target_ent && targ->target_ent->client && targ->target_ent->client->spycam) { @@ -1011,6 +1011,16 @@ void T_Damage (edict_t *in_targ, edict_t *inflictor, edict_t *in_attacker, vec3_ damage = 1; } + // Zaero + if ((targ->svflags & SVF_MONSTER) && ((targ->monsterinfo.aiflags2 & AI2_REDUCEDDAMAGE) || + ((targ->monsterinfo.aiflags2 & AI2_MONREDUCEDDAMAGE) && (inflictor->svflags & SVF_MONSTER)))) + { + damage *= targ->monsterinfo.reducedDamageAmount; + if (!damage) + damage = 1; + } + // end Zaero + client = targ->client; // PMM - defender sphere takes half damage @@ -1191,9 +1201,9 @@ void T_Damage (edict_t *in_targ, edict_t *inflictor, edict_t *in_attacker, vec3_ targ->client->invincible_framenum = level.framenum+2; targ->pain_debounce_time = max(targ->pain_debounce_time,level.time+0.3); } - else if(level.framenum - targ->client->startframe > 30) + else if (level.framenum - targ->client->startframe > 30) targ->health = targ->health - take; - else if(targ->health > 10) + else if (targ->health > 10) targ->health = max(10,targ->health - take); } else @@ -1207,27 +1217,27 @@ void T_Damage (edict_t *in_targ, edict_t *inflictor, edict_t *in_attacker, vec3_ if (targ->spawnflags & 16) // explosion only { good_damage = false; - if(mod == MOD_GRENADE) good_damage = true; - if(mod == MOD_G_SPLASH) good_damage = true; - if(mod == MOD_ROCKET) good_damage = true; - if(mod == MOD_R_SPLASH) good_damage = true; - if(mod == MOD_BFG_BLAST) good_damage = true; - if(mod == MOD_HANDGRENADE) good_damage = true; - if(mod == MOD_HG_SPLASH) good_damage = true; - if(mod == MOD_EXPLOSIVE) good_damage = true; - if(mod == MOD_BARREL) good_damage = true; - if(mod == MOD_BOMB) good_damage = true; - //Knightmare added - if(mod == MOD_PHALANX) good_damage = true; - if(mod == MOD_PHALANX_SPLASH) good_damage = true; - if(mod == MOD_TRACKER) good_damage = true; - if(mod == MOD_PROX) good_damage = true; - if(mod == MOD_PROX_SPLASH) good_damage = true; - if(mod == MOD_NUKE) good_damage = true; - if(mod == MOD_NBOMB) good_damage = true; - if(mod == MOD_DOPPLE_EXPLODE) good_damage = true; - if(mod == MOD_SHOCK_SPLASH) good_damage = true; - if(mod == MOD_ETF_SPLASH) good_damage = true; + if (mod == MOD_GRENADE) good_damage = true; + if (mod == MOD_G_SPLASH) good_damage = true; + if (mod == MOD_ROCKET) good_damage = true; + if (mod == MOD_R_SPLASH) good_damage = true; + if (mod == MOD_BFG_BLAST) good_damage = true; + if (mod == MOD_HANDGRENADE) good_damage = true; + if (mod == MOD_HG_SPLASH) good_damage = true; + if (mod == MOD_EXPLOSIVE) good_damage = true; + if (mod == MOD_BARREL) good_damage = true; + if (mod == MOD_BOMB) good_damage = true; + // Knightmare added + if (mod == MOD_PHALANX) good_damage = true; + if (mod == MOD_PHALANX_SPLASH) good_damage = true; + if (mod == MOD_TRACKER) good_damage = true; + if (mod == MOD_PROX) good_damage = true; + if (mod == MOD_PROX_SPLASH) good_damage = true; + if (mod == MOD_NUKE) good_damage = true; + if (mod == MOD_NBOMB) good_damage = true; + if (mod == MOD_DOPPLE_EXPLODE) good_damage = true; + if (mod == MOD_SHOCK_SPLASH) good_damage = true; + if (mod == MOD_ETF_SPLASH) good_damage = true; } if (!good_damage) return; } diff --git a/missionpack/g_fog.c b/missionpack/g_fog.c index 34ce3e8..774c257 100644 --- a/missionpack/g_fog.c +++ b/missionpack/g_fog.c @@ -18,7 +18,7 @@ #define GL_EXP 0x0800 #define GL_EXP2 0x0801 -#else // old sever-side fog +#else // old server-side fog #include #define __MSC__ @@ -40,7 +40,7 @@ float last_opengl_frame; int GLModels[3] = {GL_LINEAR, GL_EXP, GL_EXP2}; #ifdef KMQUAKE2_ENGINE_MOD // engine fog -int last_fog_model, last_fog_density, last_fog_near, last_fog_far, last_fog_color[3]; +int last_fog_model, last_fog_density, last_fog_near, last_fog_far, last_fog_color[3]; #else // old sever-side fog @@ -68,29 +68,32 @@ GLHINT GL_glHint; #define COLOR(r,g,b) ((((BYTE)(b)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(r))<<16))) +void Cmd_Say_f (edict_t *ent, qboolean team, qboolean arg0); void fog_fade (edict_t *self); -void Fog_ConsoleFog (void) +void Fog_ConsoleFog (edict_t *ent) { // This routine is ONLY called for console fog commands - if(deathmatch->value || coop->value) + if (!ent || !ent->client) // || ent->is_bot) return; - if(!level.active_fog) return; + if (deathmatch->value || coop->value) + return; - memcpy(&level.fog,&gfogs[0],sizeof(fog_t)); - pfog = &level.fog; + if (!level.active_fog) return; + + memcpy(&level.current_fog, &gfogs[0], sizeof(fog_t)); + pfog = &level.current_fog; // Force sensible values for linear: - if(pfog->Model==0 && pfog->Near==0. && pfog->Far==0.) + if ( (pfog->Model == 0) && (pfog->Near == 0.0f) && (pfog->Far == 0.0f) ) { - pfog->Near=64; - pfog->Far=1024; + pfog->Near = 64; + pfog->Far = 1024; } } -void Cmd_Say_f (edict_t *ent, qboolean team, qboolean arg0); void Cmd_Fog_f (edict_t *ent) { char *cmd; @@ -99,11 +102,14 @@ void Cmd_Fog_f (edict_t *ent) fog = &gfogs[0]; cmd = gi.argv(0); - if(gi.argc() < 2) + if (gi.argc() < 2) parm = NULL; else parm = gi.argv(1); + if (!ent || !ent->client) // || ent->is_bot) + return; + if (Q_stricmp (cmd, "fog_help") == 0 ) { gi.dprintf("Fog parameters for console only.\n" @@ -124,139 +130,142 @@ void Cmd_Fog_f (edict_t *ent) "Fog_Density Best results with values < 100\n\n" "Command without a value will show current setting\n"); } - else if(Q_stricmp (cmd, "fog_active") == 0 ) + else if (Q_stricmp (cmd, "fog_active") == 0 ) { - if(level.active_fog) + if (level.active_fog) { gi.dprintf("Active fog:\n" " Color: %f, %f, %f\n" " Model: %s\n", - level.fog.Color[0],level.fog.Color[1],level.fog.Color[2], - (level.fog.Model==1 ? "Exp" : (level.fog.Model==2 ? "Exp2" : "Linear"))); - if(level.fog.Model) - gi.dprintf("Density: %f\n",level.fog.Density); + level.current_fog.Color[0], level.current_fog.Color[1], level.current_fog.Color[2], + ( (level.current_fog.Model == 1) ? "Exp" : ( (level.current_fog.Model == 2) ? "Exp2" : "Linear") ) ); + if (level.current_fog.Model) + gi.dprintf("Density: %f\n", level.current_fog.Density); else { - gi.dprintf(" Near: %f\n",level.fog.Near); - gi.dprintf(" Far: %f\n",level.fog.Far); + gi.dprintf(" Near: %f\n", level.current_fog.Near); + gi.dprintf(" Far: %f\n", level.current_fog.Far); } } else gi.dprintf("No fogs currently active\n"); } - else if(Q_stricmp (cmd, "fog_stuff") == 0 ) + else if (Q_stricmp (cmd, "fog_stuff") == 0 ) { - gi.dprintf("active_fog=%d, last_active_fog=%d\n",level.active_fog,level.last_active_fog); + gi.dprintf("active_fog=%d, last_active_fog=%d\n", level.active_fog, level.last_active_fog); } - else if(Q_stricmp (cmd, "fog") == 0 ) + else if (Q_stricmp (cmd, "fog") == 0 ) { - if(parm) + if (parm) { int on; on = atoi(parm); level.active_fog = level.active_target_fog = (on ? 1 : 0); - Fog_ConsoleFog(); + Fog_ConsoleFog (ent); } gi.dprintf("fog is %s\n",(level.active_fog ? "on" : "off")); } - else if(Q_stricmp (cmd, "Fog_Red") == 0 ) + else if (Q_stricmp (cmd, "Fog_Red") == 0 ) { - if(!parm) + if (!parm) gi.dprintf("%s = %f\n",cmd,fog->Color[0]); else { level.active_fog = level.active_target_fog = 1; fog->Color[0] = max(0.0f,min(1.0f,(float)atof(parm))); - Fog_ConsoleFog(); + Fog_ConsoleFog (ent); } } - else if(Q_stricmp (cmd, "Fog_Grn") == 0 ) + else if (Q_stricmp (cmd, "Fog_Grn") == 0 ) { - if(!parm) + if (!parm) gi.dprintf("%s = %f\n",cmd,fog->Color[1]); else { level.active_fog = level.active_target_fog = 1; fog->Color[1] = max(0.0f,min(1.0f,(float)atof(parm))); - Fog_ConsoleFog(); + Fog_ConsoleFog (ent); } } - else if(Q_stricmp (cmd, "Fog_Blu") == 0 ) + else if (Q_stricmp (cmd, "Fog_Blu") == 0 ) { - if(!parm) + if (!parm) gi.dprintf("%s = %f\n",cmd,fog->Color[2]); else { level.active_fog = level.active_target_fog = 1; fog->Color[2] = max(0.0f,min(1.0f,(float)atof(parm))); - Fog_ConsoleFog(); + Fog_ConsoleFog (ent); } } - else if(Q_stricmp (cmd, "Fog_Near") == 0 ) + else if (Q_stricmp (cmd, "Fog_Near") == 0 ) { - if(!parm) + if (!parm) gi.dprintf("%s = %f\n",cmd,fog->Near); else { level.active_fog = level.active_target_fog = 1; fog->Near = (float)atof(parm); - Fog_ConsoleFog(); + Fog_ConsoleFog (ent); } } - else if(Q_stricmp (cmd, "Fog_Far") == 0 ) + else if (Q_stricmp (cmd, "Fog_Far") == 0 ) { - if(!parm) + if (!parm) gi.dprintf("%s = %f\n",cmd,fog->Far); else { level.active_fog = level.active_target_fog = 1; fog->Far = (float)atof(parm); - Fog_ConsoleFog(); + Fog_ConsoleFog (ent); } } - else if(Q_stricmp (cmd, "Fog_Model") == 0 ) + else if (Q_stricmp (cmd, "Fog_Model") == 0 ) { - if(!parm) + if (!parm) gi.dprintf("%s = %d\n0=Linear\n1=Exp\n2=Exp2\n",cmd,fog->Model); else { level.active_fog = level.active_target_fog = 1; //fog->Model = max(0,min(2,atoi(parm))); fog->Model = max(0,min(3,atoi(parm))); - if(fog->Model == 3) + if (fog->Model == 3) fog->GL_Model = GLModels[2]; else fog->GL_Model = GLModels[fog->Model]; - Fog_ConsoleFog(); + Fog_ConsoleFog (ent); } } - else if(Q_stricmp (cmd, "Fog_Density") == 0 ) + else if (Q_stricmp (cmd, "Fog_Density") == 0 ) { - if(!parm) + if (!parm) gi.dprintf("%s = %f\n",cmd,fog->Density); else { level.active_fog = level.active_target_fog = 1; fog->Density = fog->Density1 = fog->Density2 = (float)atof(parm); - Fog_ConsoleFog(); + Fog_ConsoleFog (ent); } } else if (Q_stricmp (cmd, "Fog_List") == 0 ) { - int i; - fog_t *cFog; + int i; + fog_t *cFog; + qboolean fogTName = false; - gi.dprintf("level.fogs=%d\n",level.fogs); - gi.dprintf("level.trigger_fogs=%d\n",level.trigger_fogs); - for (i=0; iTrigger ? "true" : "false")); + gi.dprintf("Fog #%d\n", i+1); + gi.dprintf("Trigger=%s\n", (cFog->Trigger ? "true" : "false")); gi.dprintf("Model=%d, Near=%g, Far=%g, Density=%g\n", cFog->Model, cFog->Near, cFog->Far, cFog->Density); - gi.dprintf("Color=%g,%g,%g\n",cFog->Color[0],cFog->Color[1],cFog->Color[2]); - gi.dprintf("Targetname=%s\n",(cFog->ent ? cFog->ent->targetname : "no ent")); + gi.dprintf("Color=%g,%g,%g\n", cFog->Color[0], cFog->Color[1], cFog->Color[2]); + fogTName = (cFog->ent && cFog->ent->targetname && (strlen(cFog->ent->targetname) > 0)); + // gi.dprintf("Targetname=%s\n", (cFog->ent ? cFog->ent->targetname : "no ent")); + gi.dprintf("Targetname=%s\n", (fogTName ? cFog->ent->targetname : "no ent")); } } else @@ -264,39 +273,38 @@ void Cmd_Fog_f (edict_t *ent) } /* -void SoftwareFog (void) +void SoftwareFog (edict_t *ent) { - edict_t *player = &g_edicts[1]; + if (!ent || !ent->client) // || ent->is_bot) + return; - player->client->fadein = level.framenum - 1; - player->client->fadehold = level.framenum + 2; - player->client->fadeout = 0; - player->client->fadecolor[0] = pfog->Color[0]; - player->client->fadecolor[1] = pfog->Color[1]; - player->client->fadecolor[2] = pfog->Color[2]; + ent->client->fadein = level.framenum - 1; + ent->client->fadehold = level.framenum + 2; + ent->client->fadeout = 0.0f; + ent->client->fadecolor[0] = pfog->Color[0]; + ent->client->fadecolor[1] = pfog->Color[1]; + ent->client->fadecolor[2] = pfog->Color[2]; - if(pfog->Model == 0) - player->client->fadealpha = pfog->Far/256.; - else if(pfog->Model == 1) - player->client->fadealpha = pfog->Density/30; + if (pfog->Model == 0) + ent->client->fadealpha = pfog->Far / 256.0f; + else if (pfog->Model == 1) + ent->client->fadealpha = pfog->Density / 30.0f; else - player->client->fadealpha = pfog->Density/15; + ent->client->fadealpha = pfog->Density / 15.0f; - if(player->client->fadealpha > 0.9) - player->client->fadealpha = 0.9; + if (ent->client->fadealpha > 0.9f) + ent->client->fadealpha = 0.9f; last_software_frame = level.framenum; - } */ -void GLFog (void) +void GLFog (edict_t *ent) { #ifdef KMQUAKE2_ENGINE_MOD // engine fog - edict_t *player_ent = &g_edicts[1]; - int fog_model, fog_density, fog_near, fog_far, fog_color[3]; + int fog_model, fog_density, fog_near, fog_far, fog_color[3]; - if (!player_ent->client) // || player_ent->is_bot) + if (!ent || !ent->client) // || ent->is_bot) return; if (pfog->GL_Model == GL_EXP) @@ -325,14 +333,14 @@ void GLFog (void) gi.WriteByte (svc_fog); // svc_fog = 21 gi.WriteByte (1); // enable message - gi.WriteByte (fog_model); // model 0, 1, or 2 - gi.WriteByte (fog_density); // density 1-100 + gi.WriteByte (fog_model); // model 0, 1, or 2 + gi.WriteByte (fog_density); // density 1-100 gi.WriteShort (fog_near); // near >0, fog_near-64, < 5000 gi.WriteByte (fog_color[0]); // red 0-255 gi.WriteByte (fog_color[1]); // green 0-255 gi.WriteByte (fog_color[2]); // blue 0-255 - gi.unicast (player_ent, true); + gi.unicast (ent, true); // write to last fog state last_fog_model = fog_model; @@ -344,7 +352,8 @@ void GLFog (void) #else // old sever-side fog GLfloat fogColor[4]; - if(!hOpenGL) return; + if (!hOpenGL) + return; fogColor[0] = pfog->Color[0]; fogColor[1] = pfog->Color[1]; fogColor[2] = pfog->Color[2]; @@ -353,7 +362,7 @@ void GLFog (void) GL_glClearColor ( fogColor[0], fogColor[1], fogColor[2], fogColor[3]); // Clear the background color to the fog color GL_glFogi (GL_FOG_MODE, pfog->GL_Model); GL_glFogfv (GL_FOG_COLOR, fogColor); - if(pfog->GL_Model == GL_LINEAR) + if (pfog->GL_Model == GL_LINEAR) { GL_glFogf (GL_FOG_START, pfog->Near); GL_glFogf (GL_FOG_END, pfog->Far); @@ -371,16 +380,16 @@ void trig_fog_fade (edict_t *self) float frames; int index; - if(!InTriggerFog) + if (!InTriggerFog) { self->nextthink = 0; return; } - if(level.framenum <= self->goal_frame) + if (level.framenum <= self->goal_frame) { index = self->fog_index-1; frames = self->goal_frame - level.framenum + 1; - if(trig_fade_fog.Model == 0) + if (trig_fade_fog.Model == 0) { trig_fade_fog.Near += (gfogs[index].Near - trig_fade_fog.Near)/frames; trig_fade_fog.Far += (gfogs[index].Far - trig_fade_fog.Far )/frames; @@ -410,11 +419,11 @@ void init_trigger_fog_delay (edict_t *self) // scan for other trigger_fog's that are currently "thinking", iow // the trigger_fog has a delay and is ramping. If found, stop the ramp for those fogs - for(i=1, e=g_edicts+i; iinuse) continue; - if(e == self) continue; - if(e->think == trig_fog_fade || e->think == fog_fade) + if (!e->inuse) continue; + if (e == self) continue; + if (e->think == trig_fog_fade || e->think == fog_fade) { e->think = NULL; e->nextthink = 0; @@ -423,15 +432,15 @@ void init_trigger_fog_delay (edict_t *self) } self->spawnflags |= FOG_ON; - if(!level.active_fog) + if (!level.active_fog) { // Fog isn't currently on - memcpy(&level.fog,&gfogs[index],sizeof(fog_t)); - level.fog.Near = 4999.; - level.fog.Far = 5000.; - level.fog.Density = 0.0; - level.fog.Density1 = 0.0; - level.fog.Density2 = 0.0; + memcpy(&level.current_fog, &gfogs[index], sizeof(fog_t)); + level.current_fog.Near = 4999.0f; + level.current_fog.Far = 5000.0f; + level.current_fog.Density = 0.0f; + level.current_fog.Density1 = 0.0f; + level.current_fog.Density2 = 0.0f; } VectorCopy(self->fog_color,gfogs[index].Color); gfogs[index].Near = self->fog_near; @@ -442,14 +451,14 @@ void init_trigger_fog_delay (edict_t *self) self->goal_frame = level.framenum + self->delay*10 + 1; self->think = trig_fog_fade; self->nextthink = level.time + FRAMETIME; - memcpy(&trig_fade_fog,&level.fog,sizeof(fog_t)); + memcpy(&trig_fade_fog, &level.current_fog, sizeof(fog_t)); level.active_fog = self->fog_index; } -void Fog (edict_t *ent) //vec3_t viewpoint) +void Fog (edict_t *ent) { edict_t *triggerfog; - edict_t *player = ent; //&g_edicts[1]; +// edict_t *player = ent; // &g_edicts[1]; vec3_t viewpoint; if (!gl_driver || !vid_ref) @@ -458,13 +467,13 @@ void Fog (edict_t *ent) //vec3_t viewpoint) if (deathmatch->value || coop->value) return; - if (!player->client) + if (!ent || !ent->client) // || ent->is_bot) return; - VectorCopy(player->s.origin, viewpoint); + VectorCopy(ent->s.origin, viewpoint); viewpoint[2] += ent->viewheight; - if(Q_stricmp(vid_ref->string,"gl")) + if (Q_stricmp(vid_ref->string, "gl") != 0) { last_software_frame = level.framenum; level.active_fog = 0; @@ -472,119 +481,117 @@ void Fog (edict_t *ent) //vec3_t viewpoint) } InTriggerFog = false; - if(level.trigger_fogs) + if (level.num_trigger_fogs) { - int i; - int trigger; - trigger=0; - for(i=1; iinuse) continue; - if(!(gfogs[i].ent->spawnflags & FOG_ON)) continue; - if(viewpoint[0] < gfogs[i].ent->absmin[0]) continue; - if(viewpoint[0] > gfogs[i].ent->absmax[0]) continue; - if(viewpoint[1] < gfogs[i].ent->absmin[1]) continue; - if(viewpoint[1] > gfogs[i].ent->absmax[1]) continue; - if(viewpoint[2] < gfogs[i].ent->absmin[2]) continue; - if(viewpoint[2] > gfogs[i].ent->absmax[2]) continue; + if (!gfogs[i].Trigger) continue; + if (!gfogs[i].ent->inuse) continue; + if (!(gfogs[i].ent->spawnflags & FOG_ON)) continue; + if (viewpoint[0] < gfogs[i].ent->absmin[0]) continue; + if (viewpoint[0] > gfogs[i].ent->absmax[0]) continue; + if (viewpoint[1] < gfogs[i].ent->absmin[1]) continue; + if (viewpoint[1] > gfogs[i].ent->absmax[1]) continue; + if (viewpoint[2] < gfogs[i].ent->absmin[2]) continue; + if (viewpoint[2] > gfogs[i].ent->absmax[2]) continue; trigger = i; break; } - if(trigger) + if (trigger) { InTriggerFog = true; triggerfog = gfogs[trigger].ent; - if(level.last_active_fog != trigger+1) + if (level.last_active_fog != trigger+1) { - if(triggerfog->delay) - init_trigger_fog_delay(triggerfog); + if (triggerfog->delay) + init_trigger_fog_delay (triggerfog); else - memcpy(&level.fog,&gfogs[trigger],sizeof(fog_t)); + memcpy(&level.current_fog, &gfogs[trigger], sizeof(fog_t)); level.active_fog = trigger+1; } - else if(triggerfog->delay) - memcpy(&level.fog,&trig_fade_fog,sizeof(fog_t)); + else if (triggerfog->delay) + memcpy(&level.current_fog, &trig_fade_fog, sizeof(fog_t)); } else { InTriggerFog = false; level.active_fog = level.active_target_fog; // if we are just coming out of a trigger_fog, force - // level.fog to last active target_fog values - if(level.active_fog && level.last_active_fog && gfogs[level.last_active_fog-1].Trigger) + // level.current_fog to last active target_fog values + if (level.active_fog && level.last_active_fog && gfogs[level.last_active_fog-1].Trigger) { edict_t *ent = gfogs[level.active_fog-1].ent; - if(ent && (ent->think == fog_fade)) + if (ent && (ent->think == fog_fade)) ent->think(ent); else - memcpy(&level.fog,&gfogs[level.active_fog-1],sizeof(fog_t)); + memcpy(&level.current_fog, &gfogs[level.active_fog-1], sizeof(fog_t)); } } } - if (!level.active_fog) { + if (!level.active_fog) + { if (level.last_active_fog) - Fog_Off (false); + Fog_Off (ent); level.last_active_fog = 0; return; } - pfog = &level.fog; - //if(level.last_active_fog != level.active_fog) - // fogtable_generated = false; + pfog = &level.current_fog; +// if (level.last_active_fog != level.active_fog) +// fogtable_generated = false; if ((pfog->Density1 != pfog->Density2) && (game.maxclients == 1) && (pfog->Model)) { float density; float dp; vec3_t vp; - AngleVectors(player->client->ps.viewangles,vp,0,0); + AngleVectors(ent->client->ps.viewangles,vp,0,0); dp = DotProduct(pfog->Dir,vp) + 1.0; density = ((pfog->Density1*dp) + (pfog->Density2*(2.0-dp)))/2.; - if(pfog->Density != density) + if (pfog->Density != density) { pfog->Density = density; //fogtable_generated = false; } } - GLFog(); + GLFog (ent); level.last_active_fog = level.active_fog; } -void Fog_Off (qboolean gameShutdown) +void Fog_Off (edict_t *ent) { if (deathmatch->value || coop->value) return; -#ifdef KMQUAKE2_ENGINE_MOD // engine fog // If game is shutting down, g_edicts will likely be invalid // and the client will clear the fog automatically - if (gameShutdown) +// if (gameShutdown) +// return; + + if (!ent || !ent->client) // || ent->is_bot) return; - { - edict_t *player_ent = &g_edicts[1]; +#ifdef KMQUAKE2_ENGINE_MOD // engine fog - if (!player_ent->client) // || player_ent->is_bot) - return; + gi.WriteByte (svc_fog); // svc_fog = 21 + gi.WriteByte (0); // disable message, remaining paramaters are ignored + gi.WriteByte (0); // 0, 1, or 2 + gi.WriteByte (0); // 1-100 + gi.WriteShort (0); // >0, fog_near-64, < 5000 + gi.WriteByte (0); // 0-255 + gi.WriteByte (0); // 0-255 + gi.WriteByte (0); // 0-255 + gi.unicast (ent, true); - gi.WriteByte (svc_fog); // svc_fog = 21 - gi.WriteByte (0); // disable message, remaining paramaters are ignored - gi.WriteByte (0); // 0, 1, or 2 - gi.WriteByte (0); // 1-100 - gi.WriteShort (0); // >0, fog_near-64, < 5000 - gi.WriteByte (0); // 0-255 - gi.WriteByte (0); // 0-255 - gi.WriteByte (0); // 0-255 - gi.unicast (player_ent, true); - - // write to last fog state - last_fog_model = last_fog_density = last_fog_near = last_fog_far = 0; - VectorSet (last_fog_color, 255, 255, 255); - } + // write to last fog state + last_fog_model = last_fog_density = last_fog_near = last_fog_far = 0; + VectorSet (last_fog_color, 255, 255, 255); #else // old sever-side fog @@ -592,7 +599,27 @@ void Fog_Off (qboolean gameShutdown) { if (!strcmp(vid_ref->string, "gl")) { - if (hOpenGL) GL_glDisable (GL_FOG); + if (hOpenGL) + GL_glDisable (GL_FOG); + } + else + { + ent->client->fadein = 0; + } + } + +#endif // KMQUAKE2_ENGINE_MOD +} + +void Fog_Off_Global (void) +{ +#ifndef KMQUAKE2_ENGINE_MOD // old sever-side fog + if (gl_driver && vid_ref) + { + if (!strcmp(vid_ref->string, "gl")) + { + if (hOpenGL) + GL_glDisable (GL_FOG); } else { @@ -602,7 +629,6 @@ void Fog_Off (qboolean gameShutdown) player->client->fadein = 0; } } - #endif // KMQUAKE2_ENGINE_MOD } @@ -617,7 +643,7 @@ void Fog_Init (void) Com_strcpy(GL_Lib,sizeof(GL_Lib), "opengl32"); Com_strcat(GL_Lib, sizeof(GL_Lib), ".dll"); hOpenGL = LoadLibrary(GL_Lib); - if(hOpenGL) + if (hOpenGL) { GL_glClearColor = (GLCLEARCOLOR)GetProcAddress(hOpenGL,"glClearColor"); GL_glDisable = (GLDISABLE)GetProcAddress(hOpenGL,"glDisable"); @@ -632,7 +658,7 @@ void Fog_Init (void) gfogs[0].Color[0] = gfogs[0].Color[1] = gfogs[0].Color[2] = 0.5; gfogs[0].Model = 1; gfogs[0].GL_Model = GLModels[1]; - gfogs[0].Density = 20.; + gfogs[0].Density = 20.0f; gfogs[0].Trigger = false; #ifdef KMQUAKE2_ENGINE_MOD // engine fog @@ -648,11 +674,11 @@ void fog_fade (edict_t *self) float frames; int index; - if(level.framenum <= self->goal_frame) + if (level.framenum <= self->goal_frame) { index = self->fog_index-1; frames = self->goal_frame - level.framenum + 1; - if(fade_fog.Model == 0) + if (fade_fog.Model == 0) { fade_fog.Near += (gfogs[index].Near - fade_fog.Near)/frames; fade_fog.Far += (gfogs[index].Far - fade_fog.Far )/frames; @@ -668,19 +694,19 @@ void fog_fade (edict_t *self) fade_fog.Color[2] += (gfogs[index].Color[2] - fade_fog.Color[2])/frames; fade_fog.GL_Model = GLModels[fade_fog.Model]; self->nextthink = level.time + FRAMETIME; - if(!InTriggerFog) - memcpy(&level.fog,&fade_fog,sizeof(fog_t)); + if (!InTriggerFog) + memcpy(&level.current_fog, &fade_fog, sizeof(fog_t)); gi.linkentity(self); } else { - //if(!(self->spawnflags & FOG_ON)) - if(self->spawnflags & FOG_TURNOFF) + // if (!(self->spawnflags & FOG_ON)) + if (self->spawnflags & FOG_TURNOFF) level.active_fog = level.active_target_fog = 0; } } -/*QUAKED target_fog (1 0 0) (-8 -8 -8) (8 8 8) ADDITIVE NEGATIVE +/*QUAKED target_fog (1 0 0) (-8 -8 -8) (8 8 8) ADDITIVE NEGATIVE TURNOFF Change the fog effects. ADDITIVE : adds the target_fog settings to the current settings @@ -705,14 +731,19 @@ void target_fog_use (edict_t *self, edict_t *other, edict_t *activator) int index; edict_t *e; + if (!self) + return; +// if (!activator || !activator->client) +// return; + self->count--; - if(self->count == 0) + if (self->count == 0) { self->think = G_FreeEdict; self->nextthink = level.time + self->delay + 1; } - if((self->spawnflags & FOG_ON) && (self->spawnflags & FOG_TOGGLE)) + if ((self->spawnflags & FOG_ON) && (self->spawnflags & FOG_TOGGLE)) { self->spawnflags &= ~FOG_ON; return; @@ -726,50 +757,50 @@ void target_fog_use (edict_t *self, edict_t *other, edict_t *activator) // scan for other target_fog's that are currently "thinking", iow // the target_fog has a delay and is ramping. If found, stop the ramp for those fogs - for(i=1, e=g_edicts+i; iinuse) continue; - if(e->think == fog_fade) + if (!e->inuse) continue; + if (e->think == fog_fade) { e->nextthink = 0; gi.linkentity(e); } } - if(self->spawnflags & FOG_TURNOFF) + if (self->spawnflags & FOG_TURNOFF) { // Fog is "turn off" only - if( self->delay && level.active_fog ) + if ( self->delay && level.active_fog ) { - gfogs[index].Far = 5000.0; - gfogs[index].Near = 4999.0; - gfogs[index].Density = 0.0; - gfogs[index].Density1 = 0.0; - gfogs[index].Density2 = 0.0; - VectorCopy(level.fog.Color,gfogs[index].Color); + gfogs[index].Far = 5000.0f; + gfogs[index].Near = 4999.0f; + gfogs[index].Density = 0.0f; + gfogs[index].Density1 = 0.0f; + gfogs[index].Density2 = 0.0f; + VectorCopy(level.current_fog.Color, gfogs[index].Color); self->goal_frame = level.framenum + self->delay*10 + 1; self->think = fog_fade; self->nextthink = level.time + FRAMETIME; level.active_fog = level.active_target_fog = self->fog_index; - memcpy(&fade_fog,&level.fog,sizeof(fog_t)); + memcpy(&fade_fog, &level.current_fog, sizeof(fog_t)); } else level.active_fog = level.active_target_fog = 0; } else { - if(self->delay) + if (self->delay) { - if(!level.active_fog) + if (!level.active_fog) { // Fog isn't currently on - memcpy(&level.fog,&gfogs[index],sizeof(fog_t)); - level.fog.Near = 4999.; - level.fog.Far = 5000.; - level.fog.Density = 0.0; - level.fog.Density1 = 0.0; - level.fog.Density2 = 0.0; + memcpy(&level.current_fog, &gfogs[index], sizeof(fog_t)); + level.current_fog.Near = 4999.0f; + level.current_fog.Far = 5000.0f; + level.current_fog.Density = 0.0f; + level.current_fog.Density1 = 0.0f; + level.current_fog.Density2 = 0.0f; } VectorCopy(self->fog_color,gfogs[index].Color); gfogs[index].Near = self->fog_near; @@ -780,9 +811,10 @@ void target_fog_use (edict_t *self, edict_t *other, edict_t *activator) self->goal_frame = level.framenum + self->delay*10 + 1; self->think = fog_fade; self->nextthink = level.time + FRAMETIME; - memcpy(&fade_fog,&level.fog,sizeof(fog_t)); - } else { - memcpy(&level.fog,&gfogs[index],sizeof(fog_t)); + memcpy(&fade_fog, &level.current_fog, sizeof(fog_t)); + } + else { + memcpy(&level.current_fog, &gfogs[index], sizeof(fog_t)); } level.active_fog = level.active_target_fog = self->fog_index; } @@ -792,12 +824,12 @@ void SP_target_fog (edict_t *self) { fog_t *fog; - if( !allow_fog->value ) + if ( !allow_fog->value ) { G_FreeEdict(self); return; } - if(deathmatch->value || coop->value) + if (deathmatch->value || coop->value) { G_FreeEdict(self); return; @@ -805,23 +837,25 @@ void SP_target_fog (edict_t *self) self->class_id = ENTITY_TARGET_FOG; - if(!level.fogs) level.fogs = 1; // 1st fog reserved for console commands + if (!level.num_fogs) + level.num_fogs = 1; // 1st fog reserved for console commands - if(level.fogs >= MAX_FOGS) + if (level.num_fogs >= MAX_FOGS) { gi.dprintf("Maximum number of fogs exceeded!\n"); G_FreeEdict(self); return; } - if( self->delay < 0.) + if ( self->delay < 0.) self->delay = 0.; - self->fog_index = level.fogs+1; - fog = &gfogs[level.fogs]; + self->fog_index = level.num_fogs+1; + fog = &gfogs[level.num_fogs]; fog->Trigger = false; - fog->Model = self->fog_model; - if (fog->Model < 0 || fog->Model > 2) fog->Model = 0; + fog->Model = self->fog_model; + if (fog->Model < 0 || fog->Model > 2) + fog->Model = 0; fog->GL_Model = GLModels[fog->Model]; VectorCopy(self->fog_color,fog->Color); if (self->spawnflags & FOG_TURNOFF) @@ -838,22 +872,22 @@ void SP_target_fog (edict_t *self) fog->Far = self->fog_far; fog->Density = self->fog_density; fog->Density1 = self->fog_density; - if(self->density == 0.) + if (self->density == 0.0f) self->density = self->fog_density; - else if(self->density < 0.) - self->density = 0.; - fog->Density2= self->density; + else if (self->density < 0.0f) + self->density = 0.0f; + fog->Density2 = self->density; } AngleVectors(self->s.angles,fog->Dir,0,0); fog->ent = self; - level.fogs++; + level.num_fogs++; self->use = target_fog_use; gi.linkentity(self); - if(self->spawnflags & FOG_ON) + if (self->spawnflags & FOG_ON) { self->spawnflags &= ~FOG_ON; - target_fog_use(self,NULL,NULL); + target_fog_use(self, NULL, NULL); } } @@ -876,11 +910,15 @@ Fog field void trigger_fog_use (edict_t *self, edict_t *other, edict_t *activator) { - if((self->spawnflags & FOG_ON) && (self->spawnflags & FOG_TOGGLE)) + + if (!self) + return; + + if ((self->spawnflags & FOG_ON) && (self->spawnflags & FOG_TOGGLE)) { self->spawnflags &= ~FOG_ON; self->count--; - if(self->count == 0) + if (self->count == 0) { self->think = G_FreeEdict; self->nextthink = level.time + FRAMETIME; @@ -896,12 +934,12 @@ void SP_trigger_fog (edict_t *self) { fog_t *fog; - if( !allow_fog->value ) + if ( !allow_fog->value ) { G_FreeEdict(self); return; } - if(deathmatch->value || coop->value) + if (deathmatch->value || coop->value) { G_FreeEdict(self); return; @@ -909,29 +947,31 @@ void SP_trigger_fog (edict_t *self) self->class_id = ENTITY_TRIGGER_FOG; - if(!level.fogs) level.fogs = 1; // 1st fog reserved for console commands + if (!level.num_fogs) + level.num_fogs = 1; // 1st fog reserved for console commands - if(level.fogs >= MAX_FOGS) + if (level.num_fogs >= MAX_FOGS) { gi.dprintf("Maximum number of fogs exceeded!\n"); G_FreeEdict(self); return; } - self->fog_index = level.fogs+1; - fog = &gfogs[level.fogs]; + self->fog_index = level.num_fogs+1; + fog = &gfogs[level.num_fogs]; fog->Trigger = true; fog->Model = self->fog_model; - if(fog->Model < 0 || fog->Model > 2) fog->Model = 0; + if ( (fog->Model < 0) || (fog->Model > 2) ) + fog->Model = 0; fog->GL_Model = GLModels[fog->Model]; VectorCopy(self->fog_color,fog->Color); - if(self->spawnflags & FOG_TURNOFF) + if (self->spawnflags & FOG_TURNOFF) { - fog->Near = 4999; - fog->Far = 5000; - fog->Density = 0; - fog->Density1 = 0; - fog->Density2 = 0; + fog->Near = 4999.0f; + fog->Far = 5000.0f; + fog->Density = 0.0f; + fog->Density1 = 0.0f; + fog->Density2 = 0.0f; } else { @@ -939,20 +979,20 @@ void SP_trigger_fog (edict_t *self) fog->Far = self->fog_far; fog->Density = self->fog_density; fog->Density1 = self->fog_density; - if(self->density == 0.) + if (self->density == 0.0f) self->density = self->fog_density; - else if(self->density < 0.) - self->density = 0.; - fog->Density2= self->density; + else if (self->density < 0.0f) + self->density = 0.0f; + fog->Density2 = self->density; } - if(!(self->spawnflags & FOG_STARTOFF)) + if (!(self->spawnflags & FOG_STARTOFF)) self->spawnflags |= FOG_ON; - AngleVectors(self->s.angles,fog->Dir,0,0); + AngleVectors(self->s.angles, fog->Dir, 0, 0); VectorClear(self->s.angles); - fog->ent = self; - level.fogs++; - level.trigger_fogs++; + fog->ent = self; + level.num_fogs++; + level.num_trigger_fogs++; self->movetype = MOVETYPE_NONE; self->svflags |= SVF_NOCLIENT; self->solid = SOLID_NOT; @@ -984,12 +1024,12 @@ void SP_trigger_fog_bbox (edict_t *self) { fog_t *fog; - if( !allow_fog->value ) + if ( !allow_fog->value ) { G_FreeEdict(self); return; } - if(deathmatch->value || coop->value) + if (deathmatch->value || coop->value) { G_FreeEdict(self); return; @@ -997,29 +1037,31 @@ void SP_trigger_fog_bbox (edict_t *self) self->class_id = ENTITY_TRIGGER_FOG; - if(!level.fogs) level.fogs = 1; // 1st fog reserved for console commands + if (!level.num_fogs) + level.num_fogs = 1; // 1st fog reserved for console commands - if(level.fogs >= MAX_FOGS) + if (level.num_fogs >= MAX_FOGS) { gi.dprintf("Maximum number of fogs exceeded!\n"); G_FreeEdict(self); return; } - self->fog_index = level.fogs+1; - fog = &gfogs[level.fogs]; + self->fog_index = level.num_fogs+1; + fog = &gfogs[level.num_fogs]; fog->Trigger = true; fog->Model = self->fog_model; - if(fog->Model < 0 || fog->Model > 2) fog->Model = 0; + if (fog->Model < 0 || fog->Model > 2) + fog->Model = 0; fog->GL_Model = GLModels[fog->Model]; VectorCopy(self->fog_color,fog->Color); - if(self->spawnflags & FOG_TURNOFF) + if (self->spawnflags & FOG_TURNOFF) { - fog->Near = 4999; - fog->Far = 5000; - fog->Density = 0; - fog->Density1 = 0; - fog->Density2 = 0; + fog->Near = 4999.0f; + fog->Far = 5000.0f; + fog->Density = 0.0f; + fog->Density1 = 0.0f; + fog->Density2 = 0.0f; } else { @@ -1027,20 +1069,20 @@ void SP_trigger_fog_bbox (edict_t *self) fog->Far = self->fog_far; fog->Density = self->fog_density; fog->Density1 = self->fog_density; - if(self->density == 0.) + if (self->density == 0.0f) self->density = self->fog_density; - else if(self->density < 0.) - self->density = 0.; - fog->Density2= self->density; + else if (self->density < 0.0f) + self->density = 0.0f; + fog->Density2 = self->density; } - if(!(self->spawnflags & FOG_STARTOFF)) + if (!(self->spawnflags & FOG_STARTOFF)) self->spawnflags |= FOG_ON; - AngleVectors(self->s.angles,fog->Dir,0,0); + AngleVectors(self->s.angles, fog->Dir, 0, 0); VectorClear(self->s.angles); - fog->ent = self; - level.fogs++; - level.trigger_fogs++; + fog->ent = self; + level.num_fogs++; + level.num_trigger_fogs++; self->movetype = MOVETYPE_NONE; self->svflags |= SVF_NOCLIENT; self->solid = SOLID_NOT; diff --git a/missionpack/g_func.c b/missionpack/g_func.c index 7e25d93..0e626e8 100644 --- a/missionpack/g_func.c +++ b/missionpack/g_func.c @@ -5323,7 +5323,7 @@ qboolean box_walkmove (edict_t *ent, float yaw, float dist) return box_movestep(ent, move, true); } -void box_water_friction(edict_t *ent) +void box_water_friction (edict_t *ent) { int i; float speed, newspeed, control; @@ -5336,9 +5336,9 @@ void box_water_friction(edict_t *ent) ent->nextthink = 0; return; } - for(i=0; i<2; i++) + for (i=0; i<2; i++) { - if(ent->velocity[i] != 0) + if (ent->velocity[i] != 0) { speed = fabs(ent->velocity[i]); control = speed < 100 ? 100 : speed; @@ -5364,7 +5364,7 @@ void box_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf vec3_t origin; edict_t *bottom, *top; - //Knightmare- ignore prox mines attached to self + // Knightmare- ignore prox mines attached to self if (!strcmp(other->classname, "prox") && other->movewith_ent && other->movewith_ent == self) return; @@ -5378,7 +5378,7 @@ void box_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf vec3_t dir, impact_v; // Check for impact damage first - if(self->health > 0) + if (self->health > 0) { VectorSubtract(other->velocity,self->velocity,impact_v); delta = VectorLength(impact_v); @@ -5391,16 +5391,16 @@ void box_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf VectorSubtract(self->s.origin,other->s.origin,dir); VectorNormalize(dir); T_Damage (self, other, other, dir, self->s.origin, vec3_origin, damage, 0, 0, MOD_FALLING); - if(self->health <= 0) return; + if (self->health <= 0) return; } } } - if(self->waterlevel==0) return; + if (self->waterlevel == 0) return; // 06/03/00 change: If either func_pushable is currently being moved // by crane, bail out. - if(self->crane_control) return; - if(other->crane_control) return; + if (self->crane_control) return; + if (other->crane_control) return; // Since func_pushables have a bounding box, impact will ALWAYS be on one of the // planes of the bounding box. The "plane" argument isn't always used, but since @@ -5413,8 +5413,8 @@ void box_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf VectorSubtract(v1,v2,v); VectorNormalize(v); axis = 0; - if(fabs(v[1]) > fabs(v[axis])) axis = 1; - if(fabs(v[2]) > fabs(v[axis])) axis = 2; + if (fabs(v[1]) > fabs(v[axis])) axis = 1; + if (fabs(v[2]) > fabs(v[axis])) axis = 2; e = 0.5; // coefficient of restitution m = (float)(other->mass)/(float)(self->mass); @@ -5429,28 +5429,29 @@ void box_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf // other two directions (so velocity doesn't change)... BUT we want // to get the bottom crate out from underneath the other one, // so we're gonna be a little "creative" - if(axis==2) + if (axis == 2) { - if(v[2] > 0) + if (v[2] > 0) { bottom = other; top = self; VectorNegate(v,v); - } else { + } + else { bottom = self; top = other; } v[2] = 0; VectorNormalize(v); - if(!VectorLength(v)) + if (!VectorLength(v)) { v[0] = crandom(); v[1] = sqrt(1.0 - v[0]*v[0]); } vslide = 10; - if(fabs(bottom->velocity[0]) < 50) + if (fabs(bottom->velocity[0]) < 50) bottom->velocity[0] += v[0] * vslide; - if(fabs(bottom->velocity[1]) < 50) + if (fabs(bottom->velocity[1]) < 50) bottom->velocity[1] += v[1] * vslide; top->velocity[0] = -bottom->velocity[0]/2; top->velocity[1] = -bottom->velocity[1]/2; @@ -5475,25 +5476,25 @@ void box_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf // if other is a monster or a player and box is on other's head and moving down, // do impact damage VectorAdd(self->s.origin,self->origin_offset,origin); - if( other->client || (other->svflags & SVF_MONSTER) ) + if ( other->client || (other->svflags & SVF_MONSTER) ) { VectorAdd (self->absmax,self->absmin,v1); VectorScale(v1,0.5,v1); VectorSubtract(v1,other->s.origin,v); VectorNormalize(v); axis = 0; - if(fabs(v[1]) > fabs(v[axis])) axis = 1; - if(fabs(v[2]) > fabs(v[axis])) axis = 2; - if(axis == 2 && v[axis] > 0) { + if (fabs(v[1]) > fabs(v[axis])) axis = 1; + if (fabs(v[2]) > fabs(v[axis])) axis = 2; + if (axis == 2 && v[axis] > 0) { v11 = VectorLength(self->velocity); VectorCopy(self->velocity,v); VectorNormalize(v); - if(!other->groundentity) + if (!other->groundentity) { other->velocity[2] = self->velocity[2]; gi.linkentity(other); } - else if((v11 > 0) && (v[2] < -0.7)) + else if ((v11 > 0) && (v[2] < -0.7)) { int damage; float delta; @@ -5512,7 +5513,7 @@ void box_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf return; } } - else if( (other->groundentity == self) && (self->velocity[2] > 0)) + else if ( (other->groundentity == self) && (self->velocity[2] > 0)) { self->bounce_me = 2; other->velocity[2] = self->velocity[2]; @@ -5538,7 +5539,7 @@ void box_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf // something else, return if ((other->client->push != NULL) && (other->client->push != self)) { - if(self->activator == other) self->activator = NULL; + if (self->activator == other) self->activator = NULL; return; } @@ -5560,7 +5561,7 @@ void box_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf // if func_pushable isn't in front of pusher, do nothing if (!point_infront(other,v1)) { - if(self->activator == other) self->activator = NULL; + if (self->activator == other) self->activator = NULL; return; } @@ -5573,9 +5574,10 @@ void box_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf } // if this box has another box stacked on top, balk - if( CrateOnTop (NULL, self) ) + if ( CrateOnTop (NULL, self) ) { - if(self->activator == other) self->activator = NULL; + if (self->activator == other) + self->activator = NULL; return; } @@ -5592,7 +5594,7 @@ void box_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf ratio = (float)other->mass / (float)self->mass; other->client->maxvelocity = 20. * ratio; // Knightmare- don't autoswitch if client-side chasecam is on - if(tpp_auto->value && (!cl_thirdperson->value || deathmatch->value || coop->value) + if (tpp_auto->value && (!cl_thirdperson->value || deathmatch->value || coop->value) && !other->client->chasetoggle && !other->client->chaseactive) { // Cmd_Chasecam_Toggle(other); @@ -5624,8 +5626,8 @@ void SP_func_pushable (edict_t *self) self->class_id = ENTITY_FUNC_PUSHABLE; - //Knightmare- precache different gib types - PrecacheDebris(self->gib_type); + // Knightmare- precache different gib types + PrecacheDebris (self->gib_type); gi.setmodel (self, self->model); @@ -5641,15 +5643,15 @@ void SP_func_pushable (edict_t *self) } // Game places a 2 unit border around brush model absmin and absmax - VectorAdd(self->mins,border,self->mins); - VectorSubtract(self->maxs,border,self->maxs); - VectorAdd(self->absmin,border,self->absmin); - VectorSubtract(self->absmax,border,self->absmax); + VectorAdd (self->mins, border, self->mins); + VectorSubtract (self->maxs, border, self->maxs); + VectorAdd (self->absmin, border, self->absmin); + VectorSubtract (self->absmax, border, self->absmax); if (!self->mass) self->mass = 400; - if (st.item) //Knightmare- item support + if (st.item) // Knightmare- item support { self->item = FindItemByClassname (st.item); if (!self->item) @@ -5704,7 +5706,7 @@ void SP_func_pushable (edict_t *self) break; } - if(self->sounds && !VectorLength(self->s.origin) ) + if (self->sounds && !VectorLength(self->s.origin) ) { edict_t *speaker; diff --git a/missionpack/g_func_decs.h b/missionpack/g_func_decs.h index e58384d..351cd8f 100644 --- a/missionpack/g_func_decs.h +++ b/missionpack/g_func_decs.h @@ -1,3 +1,9 @@ +extern void fire_flare ( edict_t * self , vec3_t start , vec3_t dir , int damage , int speed , float damage_radius , int radius_damage ) ; +extern void flare_think ( edict_t * self ) ; +extern void flare_flash ( edict_t * ent ) ; +extern void SP_trigger_laser ( edict_t * self ) ; +extern void trigger_laser_on ( edict_t * self ) ; +extern void trigger_laser_think ( edict_t * self ) ; extern void SP_monster_sentien ( edict_t * self ) ; extern void SP_monster_sentien_precache ( void ) ; extern void create_sentien_laser ( edict_t * self ) ; @@ -36,6 +42,26 @@ extern void sentien_sound_footstep ( edict_t * self ) ; extern void sentien_laser_off ( edict_t * self ) ; extern void sentien_laser_on ( edict_t * self ) ; extern void sentien_laser_think ( edict_t * self ) ; +extern void SP_func_barrier ( edict_t * self ) ; +extern void barrier_touch ( edict_t * self , edict_t * other , cplane_t * plane , csurface_t * surf ) ; +extern void barrier_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; +extern void barrier_think ( edict_t * self ) ; +extern qboolean thruBarrier ( edict_t * targ , edict_t * inflictor ) ; +extern void SP_misc_commdish ( edict_t * self ) ; +extern void Use_CommDish ( edict_t * ent , edict_t * other , edict_t * activator ) ; +extern void Anim_CommDish ( edict_t * self ) ; +extern void SP_misc_seat ( edict_t * self ) ; +extern void SP_misc_crate_small ( edict_t * self ) ; +extern void SP_misc_crate_medium ( edict_t * self ) ; +extern void SP_misc_crate ( edict_t * self ) ; +extern void setupCrate ( edict_t * self ) ; +extern qboolean EMPNukeCheck ( edict_t * ent , vec3_t pos ) ; +extern void fire_empnuke ( edict_t * ent , vec3_t center , int radius ) ; +extern void empBlastAnim ( edict_t * ent ) ; +extern void empnukeFinish ( edict_t * ent ) ; +extern void Weapon_EMPNuke ( edict_t * ent ) ; +extern void weapon_EMPNuke_fire ( edict_t * ent ) ; +extern void hound_createHound ( edict_t * self , float healthPercent ) ; extern void SP_monster_hound ( edict_t * self ) ; extern void SP_monster_hound_precache ( void ) ; extern void hound_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; @@ -57,6 +83,83 @@ extern void hound_run ( edict_t * self ) ; extern void hound_stand ( edict_t * self ) ; extern void hound_sight ( edict_t * self , edict_t * other ) ; extern void hound_launch ( edict_t * self ) ; +extern void SP_monster_handler ( edict_t * self ) ; +extern void SP_monster_handler_precache ( void ) ; +extern void handler_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; +extern void handler_dead ( edict_t * self ) ; +extern void handler_attack ( edict_t * self ) ; +extern void StartCount ( edict_t * self ) ; +extern void CheckForEnemy ( edict_t * self ) ; +extern void CheckIdleLoop ( edict_t * self ) ; +extern void handler_createHound ( edict_t * self ) ; +extern void handler_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; +extern void handler_stand ( edict_t * self ) ; +extern void handler_standSitWhatNext ( edict_t * self ) ; +extern void handler_standWhatNext ( edict_t * self ) ; +extern void handler_sitdown ( edict_t * self ) ; +extern void handler_standup ( edict_t * self ) ; +extern void handler_scratch ( edict_t * self ) ; +extern void handler_sight ( edict_t * self , edict_t * other ) ; +extern void SP_target_zboss_target ( edict_t * self ) ; +extern void trigger_zboss ( edict_t * self , edict_t * other , edict_t * activator ) ; +extern void SP_monster_zboss ( edict_t * self ) ; +extern void SP_monster_zboss_precache ( void ) ; +extern void zboss_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; +extern void FireDeadGrapple ( edict_t * self ) ; +extern void DeadHookTouch ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; +extern void FireDeadCannon3 ( edict_t * self ) ; +extern void FireDeadCannon2 ( edict_t * self ) ; +extern void FireDeadCannon1 ( edict_t * self ) ; +extern void FireDeadRocket7 ( edict_t * self ) ; +extern void FireDeadRocket6 ( edict_t * self ) ; +extern void FireDeadRocket5 ( edict_t * self ) ; +extern void FireDeadRocket4 ( edict_t * self ) ; +extern void FireDeadRocket3 ( edict_t * self ) ; +extern void FireDeadRocket2 ( edict_t * self ) ; +extern void FireDeadRocket1 ( edict_t * self ) ; +extern void zboss_dead ( edict_t * self ) ; +extern void zboss_attack ( edict_t * self ) ; +extern void zboss_chooseNextAttack ( edict_t * self ) ; +extern void zboss_postcannon ( edict_t * self ) ; +extern void zboss_fireCannons ( edict_t * self ) ; +extern void FireCannon ( edict_t * self ) ; +extern void fire_plasmaCannon ( edict_t * self , vec3_t start , vec3_t aimdir , int damage , int speed , float timer , float damage_radius , float distance ) ; +extern void Plasmaball_Touch ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; +extern void Plasmaball_Explode ( edict_t * ent ) ; +extern void PlasmaballBlastAnim ( edict_t * ent ) ; +extern void zboss_chooseHookRocket ( edict_t * self ) ; +extern void zboss_posthook ( edict_t * self ) ; +extern void zboss_reelInGraaple ( edict_t * self ) ; +extern void FireHook ( edict_t * self ) ; +extern void HookThink ( edict_t * self ) ; +extern void HookTouch ( edict_t * ent , edict_t * other , cplane_t * plane , csurface_t * surf ) ; +extern void HookDragThink ( edict_t * self ) ; +extern void zboss_reelInGraaple2 ( edict_t * self ) ; +extern void FireRocket ( edict_t * self ) ; +extern void FireFlare ( edict_t * self ) ; +extern void zboss_reloadRockets ( edict_t * self ) ; +extern void zboss_melee ( edict_t * self ) ; +extern void zboss_melee2 ( edict_t * self ) ; +extern void zboss_swing ( edict_t * self ) ; +extern void zboss_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; +extern void zboss_stand ( edict_t * self ) ; +extern void zboss_run2 ( edict_t * self ) ; +extern void zboss_run ( edict_t * self ) ; +extern void zboss_walk2 ( edict_t * self ) ; +extern void zboss_walk ( edict_t * self ) ; +extern void zboss_postWalkRun ( edict_t * self ) ; +extern void zboss_standidle ( edict_t * self ) ; +extern void possibleBossTaunt ( edict_t * self ) ; +extern void zboss_sight ( edict_t * self , edict_t * other ) ; +extern void zboss_walksound ( edict_t * self ) ; +extern void ai_schoolCharge ( edict_t * self , float dist ) ; +extern void ai_schoolWalk ( edict_t * self , float dist ) ; +extern void ai_schoolRun ( edict_t * self , float dist ) ; +extern void ai_schoolStand ( edict_t * self , float dist ) ; +extern int zSchoolMonsters ( edict_t * self , float dist , int runStyle , float * currentSpeed ) ; +extern int zFindRoamYaw ( edict_t * self , float distcheck ) ; +extern int zSchoolAllVisiable ( edict_t * self ) ; +extern void zCreateRaduisList ( edict_t * self ) ; extern void Info_SetValueForKey ( char * s , char * key , char * value ) ; extern qboolean Info_Validate ( char * s ) ; extern void Info_RemoveKey ( char * s , char * key ) ; @@ -150,7 +253,7 @@ extern void Weapon_HyperBlaster ( edict_t * ent ) ; extern void Weapon_HyperBlaster_Fire ( edict_t * ent , qboolean altfire ) ; extern void Weapon_Blaster ( edict_t * ent ) ; extern void Weapon_Blaster_Fire ( edict_t * ent , qboolean altfire ) ; -extern void Blaster_Fire ( edict_t * ent , vec3_t g_offset , int damage , qboolean hyper , int effect , int color ) ; +extern int Blaster_Fire ( edict_t * ent , vec3_t g_offset , int damage , qboolean hyper , int effect , int color ) ; extern void Weapon_HomingMissileLauncher ( edict_t * ent ) ; extern void Weapon_HomingMissileLauncher_Fire ( edict_t * ent , qboolean altfire ) ; extern void Weapon_RocketLauncher ( edict_t * ent ) ; @@ -870,7 +973,9 @@ extern void insane_scream ( edict_t * self ) ; extern void insane_moan ( edict_t * self ) ; extern void insane_shake ( edict_t * self ) ; extern void insane_fist ( edict_t * self ) ; +extern void handler_ConvertToInfantry ( edict_t * self ) ; extern void SP_monster_infantry ( edict_t * self ) ; +extern void SP_monster_infantry_precache ( void ) ; extern void infantry_sidestep ( edict_t * self ) ; extern void infantry_duck ( edict_t * self , float eta ) ; extern qboolean infantry_blocked ( edict_t * self , float dist ) ; @@ -1790,6 +1895,9 @@ extern void ReflectTrail ( int type , vec3_t start , vec3_t end ) ; extern void ReflectExplosion ( int type , vec3_t origin ) ; extern void SV_Physics_NewToss ( edict_t * ent ) ; extern void G_RunEntity ( edict_t * ent ) ; +extern void SV_Physics_Ride ( edict_t * ent ) ; +extern void adjustRiders ( edict_t * ent ) ; +extern void SV_Physics_FallFloat ( edict_t * ent ) ; extern void SV_Physics_Conveyor ( edict_t * ent ) ; extern void SV_Physics_Debris ( edict_t * ent ) ; extern trace_t SV_DebrisEntity ( edict_t * ent , vec3_t push ) ; @@ -2524,13 +2632,14 @@ extern void SP_target_fog ( edict_t * self ) ; extern void target_fog_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void fog_fade ( edict_t * self ) ; extern void Fog_Init ( void ) ; -extern void Fog_Off ( qboolean gameShutdown ) ; +extern void Fog_Off_Global ( void ) ; +extern void Fog_Off ( edict_t * ent ) ; extern void Fog ( edict_t * ent ) ; extern void init_trigger_fog_delay ( edict_t * self ) ; extern void trig_fog_fade ( edict_t * self ) ; -extern void GLFog ( void ) ; +extern void GLFog ( edict_t * ent ) ; extern void Cmd_Fog_f ( edict_t * ent ) ; -extern void Fog_ConsoleFog ( void ) ; +extern void Fog_ConsoleFog ( edict_t * ent ) ; extern void SP_crane_reset ( edict_t * self ) ; extern void crane_reset_use ( edict_t * self , edict_t * other , edict_t * activator ) ; extern void crane_reset_go ( edict_t * temp ) ; diff --git a/missionpack/g_func_list.h b/missionpack/g_func_list.h index a922b89..36e558b 100644 --- a/missionpack/g_func_list.h +++ b/missionpack/g_func_list.h @@ -1,3 +1,9 @@ +{"fire_flare", (byte *)fire_flare}, +{"flare_think", (byte *)flare_think}, +{"flare_flash", (byte *)flare_flash}, +{"SP_trigger_laser", (byte *)SP_trigger_laser}, +{"trigger_laser_on", (byte *)trigger_laser_on}, +{"trigger_laser_think", (byte *)trigger_laser_think}, {"SP_monster_sentien", (byte *)SP_monster_sentien}, {"SP_monster_sentien_precache", (byte *)SP_monster_sentien_precache}, {"create_sentien_laser", (byte *)create_sentien_laser}, @@ -36,6 +42,26 @@ {"sentien_laser_off", (byte *)sentien_laser_off}, {"sentien_laser_on", (byte *)sentien_laser_on}, {"sentien_laser_think", (byte *)sentien_laser_think}, +{"SP_func_barrier", (byte *)SP_func_barrier}, +{"barrier_touch", (byte *)barrier_touch}, +{"barrier_pain", (byte *)barrier_pain}, +{"barrier_think", (byte *)barrier_think}, +{"thruBarrier", (byte *)thruBarrier}, +{"SP_misc_commdish", (byte *)SP_misc_commdish}, +{"Use_CommDish", (byte *)Use_CommDish}, +{"Anim_CommDish", (byte *)Anim_CommDish}, +{"SP_misc_seat", (byte *)SP_misc_seat}, +{"SP_misc_crate_small", (byte *)SP_misc_crate_small}, +{"SP_misc_crate_medium", (byte *)SP_misc_crate_medium}, +{"SP_misc_crate", (byte *)SP_misc_crate}, +{"setupCrate", (byte *)setupCrate}, +{"EMPNukeCheck", (byte *)EMPNukeCheck}, +{"fire_empnuke", (byte *)fire_empnuke}, +{"empBlastAnim", (byte *)empBlastAnim}, +{"empnukeFinish", (byte *)empnukeFinish}, +{"Weapon_EMPNuke", (byte *)Weapon_EMPNuke}, +{"weapon_EMPNuke_fire", (byte *)weapon_EMPNuke_fire}, +{"hound_createHound", (byte *)hound_createHound}, {"SP_monster_hound", (byte *)SP_monster_hound}, {"SP_monster_hound_precache", (byte *)SP_monster_hound_precache}, {"hound_die", (byte *)hound_die}, @@ -57,6 +83,83 @@ {"hound_stand", (byte *)hound_stand}, {"hound_sight", (byte *)hound_sight}, {"hound_launch", (byte *)hound_launch}, +{"SP_monster_handler", (byte *)SP_monster_handler}, +{"SP_monster_handler_precache", (byte *)SP_monster_handler_precache}, +{"handler_die", (byte *)handler_die}, +{"handler_dead", (byte *)handler_dead}, +{"handler_attack", (byte *)handler_attack}, +{"StartCount", (byte *)StartCount}, +{"CheckForEnemy", (byte *)CheckForEnemy}, +{"CheckIdleLoop", (byte *)CheckIdleLoop}, +{"handler_createHound", (byte *)handler_createHound}, +{"handler_pain", (byte *)handler_pain}, +{"handler_stand", (byte *)handler_stand}, +{"handler_standSitWhatNext", (byte *)handler_standSitWhatNext}, +{"handler_standWhatNext", (byte *)handler_standWhatNext}, +{"handler_sitdown", (byte *)handler_sitdown}, +{"handler_standup", (byte *)handler_standup}, +{"handler_scratch", (byte *)handler_scratch}, +{"handler_sight", (byte *)handler_sight}, +{"SP_target_zboss_target", (byte *)SP_target_zboss_target}, +{"trigger_zboss", (byte *)trigger_zboss}, +{"SP_monster_zboss", (byte *)SP_monster_zboss}, +{"SP_monster_zboss_precache", (byte *)SP_monster_zboss_precache}, +{"zboss_die", (byte *)zboss_die}, +{"FireDeadGrapple", (byte *)FireDeadGrapple}, +{"DeadHookTouch", (byte *)DeadHookTouch}, +{"FireDeadCannon3", (byte *)FireDeadCannon3}, +{"FireDeadCannon2", (byte *)FireDeadCannon2}, +{"FireDeadCannon1", (byte *)FireDeadCannon1}, +{"FireDeadRocket7", (byte *)FireDeadRocket7}, +{"FireDeadRocket6", (byte *)FireDeadRocket6}, +{"FireDeadRocket5", (byte *)FireDeadRocket5}, +{"FireDeadRocket4", (byte *)FireDeadRocket4}, +{"FireDeadRocket3", (byte *)FireDeadRocket3}, +{"FireDeadRocket2", (byte *)FireDeadRocket2}, +{"FireDeadRocket1", (byte *)FireDeadRocket1}, +{"zboss_dead", (byte *)zboss_dead}, +{"zboss_attack", (byte *)zboss_attack}, +{"zboss_chooseNextAttack", (byte *)zboss_chooseNextAttack}, +{"zboss_postcannon", (byte *)zboss_postcannon}, +{"zboss_fireCannons", (byte *)zboss_fireCannons}, +{"FireCannon", (byte *)FireCannon}, +{"fire_plasmaCannon", (byte *)fire_plasmaCannon}, +{"Plasmaball_Touch", (byte *)Plasmaball_Touch}, +{"Plasmaball_Explode", (byte *)Plasmaball_Explode}, +{"PlasmaballBlastAnim", (byte *)PlasmaballBlastAnim}, +{"zboss_chooseHookRocket", (byte *)zboss_chooseHookRocket}, +{"zboss_posthook", (byte *)zboss_posthook}, +{"zboss_reelInGraaple", (byte *)zboss_reelInGraaple}, +{"FireHook", (byte *)FireHook}, +{"HookThink", (byte *)HookThink}, +{"HookTouch", (byte *)HookTouch}, +{"HookDragThink", (byte *)HookDragThink}, +{"zboss_reelInGraaple2", (byte *)zboss_reelInGraaple2}, +{"FireRocket", (byte *)FireRocket}, +{"FireFlare", (byte *)FireFlare}, +{"zboss_reloadRockets", (byte *)zboss_reloadRockets}, +{"zboss_melee", (byte *)zboss_melee}, +{"zboss_melee2", (byte *)zboss_melee2}, +{"zboss_swing", (byte *)zboss_swing}, +{"zboss_pain", (byte *)zboss_pain}, +{"zboss_stand", (byte *)zboss_stand}, +{"zboss_run2", (byte *)zboss_run2}, +{"zboss_run", (byte *)zboss_run}, +{"zboss_walk2", (byte *)zboss_walk2}, +{"zboss_walk", (byte *)zboss_walk}, +{"zboss_postWalkRun", (byte *)zboss_postWalkRun}, +{"zboss_standidle", (byte *)zboss_standidle}, +{"possibleBossTaunt", (byte *)possibleBossTaunt}, +{"zboss_sight", (byte *)zboss_sight}, +{"zboss_walksound", (byte *)zboss_walksound}, +{"ai_schoolCharge", (byte *)ai_schoolCharge}, +{"ai_schoolWalk", (byte *)ai_schoolWalk}, +{"ai_schoolRun", (byte *)ai_schoolRun}, +{"ai_schoolStand", (byte *)ai_schoolStand}, +{"zSchoolMonsters", (byte *)zSchoolMonsters}, +{"zFindRoamYaw", (byte *)zFindRoamYaw}, +{"zSchoolAllVisiable", (byte *)zSchoolAllVisiable}, +{"zCreateRaduisList", (byte *)zCreateRaduisList}, {"Info_SetValueForKey", (byte *)Info_SetValueForKey}, {"Info_Validate", (byte *)Info_Validate}, {"Info_RemoveKey", (byte *)Info_RemoveKey}, @@ -870,7 +973,9 @@ {"insane_moan", (byte *)insane_moan}, {"insane_shake", (byte *)insane_shake}, {"insane_fist", (byte *)insane_fist}, +{"handler_ConvertToInfantry", (byte *)handler_ConvertToInfantry}, {"SP_monster_infantry", (byte *)SP_monster_infantry}, +{"SP_monster_infantry_precache", (byte *)SP_monster_infantry_precache}, {"infantry_sidestep", (byte *)infantry_sidestep}, {"infantry_duck", (byte *)infantry_duck}, {"infantry_blocked", (byte *)infantry_blocked}, @@ -1790,6 +1895,9 @@ {"ReflectExplosion", (byte *)ReflectExplosion}, {"SV_Physics_NewToss", (byte *)SV_Physics_NewToss}, {"G_RunEntity", (byte *)G_RunEntity}, +{"SV_Physics_Ride", (byte *)SV_Physics_Ride}, +{"adjustRiders", (byte *)adjustRiders}, +{"SV_Physics_FallFloat", (byte *)SV_Physics_FallFloat}, {"SV_Physics_Conveyor", (byte *)SV_Physics_Conveyor}, {"SV_Physics_Debris", (byte *)SV_Physics_Debris}, {"SV_DebrisEntity", (byte *)SV_DebrisEntity}, @@ -2524,6 +2632,7 @@ {"target_fog_use", (byte *)target_fog_use}, {"fog_fade", (byte *)fog_fade}, {"Fog_Init", (byte *)Fog_Init}, +{"Fog_Off_Global", (byte *)Fog_Off_Global}, {"Fog_Off", (byte *)Fog_Off}, {"Fog", (byte *)Fog}, {"init_trigger_fog_delay", (byte *)init_trigger_fog_delay}, diff --git a/missionpack/g_items.c b/missionpack/g_items.c index c1f4607..fe16d58 100644 --- a/missionpack/g_items.c +++ b/missionpack/g_items.c @@ -435,7 +435,7 @@ qboolean Pickup_Bandolier (edict_t *ent, edict_t *other) gitem_t *item; int index; - //Knightmare- override ammo pickup values with cvars + // Knightmare- override ammo pickup values with cvars SetAmmoPickupValues (); if (other->client->pers.max_bullets < sk_bando_bullets->value) @@ -450,15 +450,20 @@ qboolean Pickup_Bandolier (edict_t *ent, edict_t *other) if (other->client->pers.max_magslug < sk_bando_magslugs->value) other->client->pers.max_magslug = sk_bando_magslugs->value; - //PMM + // PMM if (other->client->pers.max_flechettes < sk_bando_flechettes->value) other->client->pers.max_flechettes = sk_bando_flechettes->value; if (other->client->pers.max_disruptors < sk_bando_rounds->value) other->client->pers.max_disruptors = sk_bando_rounds->value; + // pmm + if (other->client->pers.max_fuel < sk_bando_fuel->value) other->client->pers.max_fuel = sk_bando_fuel->value; - //pmm + // Zaero +/* if (other->client->pers.max_flares < sk_bando_flares->value) + other->client->pers.max_flares = sk_bando_flares->value;*/ + // end Zaero item = FindItem("Bullets"); if (item) @@ -489,7 +494,7 @@ qboolean Pickup_Pack (edict_t *ent, edict_t *other) gitem_t *item; int index; - //Knightmare- override ammo pickup values with cvars + // Knightmare- override ammo pickup values with cvars SetAmmoPickupValues (); if (other->client->pers.max_bullets < sk_pack_bullets->value) @@ -509,7 +514,7 @@ qboolean Pickup_Pack (edict_t *ent, edict_t *other) if (other->client->pers.max_trap < sk_pack_traps->value) other->client->pers.max_trap = sk_pack_traps->value; - //PMM + // PMM if (other->client->pers.max_flechettes < sk_pack_flechettes->value) other->client->pers.max_flechettes = sk_pack_flechettes->value; if (other->client->pers.max_prox < sk_pack_prox->value) @@ -522,9 +527,24 @@ qboolean Pickup_Pack (edict_t *ent, edict_t *other) other->client->pers.max_shockspheres = sk_pack_shocksphere->value; if (other->client->pers.max_homing_rockets < sk_pack_rockets->value) other->client->pers.max_homing_rockets = sk_pack_rockets->value; + // pmm + if (other->client->pers.max_fuel < sk_pack_fuel->value) other->client->pers.max_fuel = sk_pack_fuel->value; - //pmm + + // Zaero +/* if (other->client->pers.max_flares < sk_pack_flares->value) + other->client->pers.max_flares = sk_pack_flares->value; + if (other->client->pers.max_tbombs < sk_pack_tbombs->value) + other->client->pers.max_tbombs = sk_pack_tbombs->value; + if (other->client->pers.max_a2k < sk_pack_a2k->value) + other->client->pers.max_a2k = sk_pack_a2k->value; + if (other->client->pers.max_empnuke < sk_pack_empnuke->value) + other->client->pers.max_empnuke = sk_pack_empnuke->value; + if (other->client->pers.max_plasmashield < sk_pack_plasmashield->value) + other->client->pers.max_plasmashield = sk_pack_plasmashield->value;*/ + // end Zaero + item = FindItem("Bullets"); if (item) @@ -588,7 +608,7 @@ qboolean Pickup_Pack (edict_t *ent, edict_t *other) other->client->pers.inventory[index] = other->client->pers.max_magslug; } -//PMM +// PMM item = FindItem("Flechettes"); if (item && sk_pack_give_rogue_ammo->value) { @@ -605,7 +625,7 @@ qboolean Pickup_Pack (edict_t *ent, edict_t *other) if (other->client->pers.inventory[index] > other->client->pers.max_disruptors) other->client->pers.inventory[index] = other->client->pers.max_disruptors; } -//pmm +// pmm if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value)) SetRespawn (ent, ent->item->quantity); @@ -3890,34 +3910,6 @@ warehouse circuits "" //precache }, -// New item (sorta) for Citadel pack by Andrea Rosa -#ifdef CITADELMOD_FEATURES -// 69 -/*QUAKED key_mystery (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN -key for Citadel Pack 3.0 -*/ - { - "key_mystery", - Pickup_Key, - NULL, - Drop_General, - NULL, - "items/pkup.wav", - "models/items/keys/mystery/tris.md2", 0, EF_ROTATE, - NULL, - "k_mystery", - "Mystery Key", - 2, - 0, - NULL, - IT_STAY_COOP|IT_KEY, - 0, - NULL, - 0, - "" //precache - }, -#endif - // 69 /*QUAKED key_pyramid (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN key for the entrance of jail3 @@ -4172,6 +4164,179 @@ marker for airstrike // ====================================== // 79 +// New item (sorta) for Citadel pack by Andrea Rosa +/*QUAKED key_mystery (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN +key for Citadel Pack 3.0 +*/ + { + "key_mystery", + Pickup_Key, + NULL, + Drop_General, + NULL, + "items/pkup.wav", + "models/items/keys/mystery/tris.md2", 0, EF_ROTATE, + NULL, + "k_mystery", + "Mystery Key", + 2, + 0, + NULL, + IT_STAY_COOP|IT_KEY, + 0, + NULL, + 0, + "" //precache + }, + +// Zaero keys +// 80 +/*QUAKED key_landing_arena (0 .5 .8) (-16 -16 -16) (16 16 16) +landing arena key - blue +*/ + { + "key_landing_area", + Pickup_Key, + NULL, + Drop_General, + NULL, + "items/pkup.wav", + "models/items/keys/key/tris.md2", 0, EF_ROTATE, + NULL, + "k_bluekey", + "Airfield Pass", + 2, + 0, + NULL, + IT_STAY_COOP|IT_KEY, + 0, + NULL, + 0, +/* precache */ "" + }, + +// 81 +/*QUAKED key_lab (0 .5 .8) (-16 -16 -16) (16 16 16) +security pass for the laboratory +*/ + { + "key_lab", + Pickup_Key, + NULL, + Drop_General, + NULL, + "items/pkup.wav", + "models/items/keys/pass/tris.md2", 0, EF_ROTATE, + NULL, + "k_security", + "Laboratory Key", + 2, + 0, + NULL, + IT_STAY_COOP|IT_KEY, + 0, + NULL, + 0, +/* precache */ "" + }, + +// 82 +/*QUAKED key_clearancepass (0 .5 .8) (-16 -16 -16) (16 16 16) +*/ + { + "key_clearancepass", + Pickup_Key, + NULL, + Drop_General, + NULL, + "items/pkup.wav", + "models/items/keys/pass/tris.md2", 0, EF_ROTATE, + NULL, + "k_security", + "Clearance Pass", + 2, + 0, + NULL, + IT_STAY_COOP|IT_KEY, + 0, + NULL, + 0, +/* precache */ "" + }, + +// 83 +/*QUAKED key_energy (0 .5 .8) (-16 -16 -16) (16 16 16) +*/ + { + "key_energy", + Pickup_Key, + NULL, + Drop_General, + NULL, + "items/pkup.wav", + "models/items/keys/energy/tris.md2", 0, EF_ROTATE, + NULL, + "k_energy", + "Energy Key", + 2, + 0, + NULL, + IT_STAY_COOP|IT_KEY, + 0, + NULL, + 0, +/* precache */ "" + }, + +// 84 +/*QUAKED key_lava (0 .5 .8) (-16 -16 -16) (16 16 16) +*/ + { + "key_lava", + Pickup_Key, + NULL, + Drop_General, + NULL, + "items/pkup.wav", + "models/items/keys/lava/tris.md2", 0, EF_ROTATE, + NULL, + "k_lava", + "Lava Key", + 2, + 0, + NULL, + IT_STAY_COOP|IT_KEY, + 0, + NULL, + 0, +/* precache */ "" + }, + +// 85 +/*QUAKED key_slime (0 .5 .8) (-16 -16 -16) (16 16 16) +*/ + { + "key_slime", + Pickup_Key, + NULL, + Drop_General, + NULL, + "items/pkup.wav", + "models/items/keys/slime/tris.md2", 0, EF_ROTATE, + NULL, + "k_slime", + "Slime Key", + 2, + 0, + NULL, + IT_STAY_COOP|IT_KEY, + 0, + NULL, + 0, +/* precache */ "" + }, + +// 86 /*QUAKED key_q1_gold (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN medevial door key - gold model="models/items/q1keys/gold/tris.md2" @@ -4197,7 +4362,7 @@ model="models/items/q1keys/gold/tris.md2" /* precache */ "" }, -// 80 +// 87 /*QUAKED key_q1_silver (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN medevial door key - silver model="models/items/q1keys/silver/tris.md2" @@ -4223,7 +4388,7 @@ model="models/items/q1keys/silver/tris.md2" /* precache */ "" }, -// 81 +// 88 /*QUAKED runekey_q1_gold (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN runic door key - gold model="models/items/q1keys/gold/rune/tris.md2" @@ -4249,7 +4414,7 @@ model="models/items/q1keys/gold/rune/tris.md2" /* precache */ "" }, -// 82 +// 89 /*QUAKED runekey_q1_silver (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN runic door key - silver model="models/items/q1keys/silver/rune/tris.md2" @@ -4275,7 +4440,7 @@ model="models/items/q1keys/silver/rune/tris.md2" /* precache */ "" }, -// 83 +// 90 /*QUAKED basekey_q1_gold (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN base door key - gold model="models/items/q1keys/gold/base/tris.md2" @@ -4301,7 +4466,7 @@ model="models/items/q1keys/gold/base/tris.md2" /* precache */ "" }, -// 84 +// 91 /*QUAKED basekey_q1_silver (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN base door key - silver model="models/items/q1keys/silver/base/tris.md2" diff --git a/missionpack/g_local.h b/missionpack/g_local.h index 93739d4..1b0cd3d 100644 --- a/missionpack/g_local.h +++ b/missionpack/g_local.h @@ -18,6 +18,23 @@ #include "km_cvar.h" #define JETPACK_MOD +// Zaero +// some custom defines +//#define USE_ZAERO_ITEMS_WEAPONS // enable for Zaero player weapons +#ifdef Z_MAX +#undef Z_MAX +#endif // Z_MAX +#define Z_MAX(a,b) ((a) > (b) ? (a) : (b)) + +#ifdef Z_MIN +#undef Z_MIN +#endif // Z_MIN +#define Z_MIN(a,b) ((a) < (b) ? (a) : (b)) + +#define Z_MALLOC(size) gi.TagMalloc(size, TAG_GAME) +#define Z_FREE(block) gi.TagFree(block) +// end Zaero + // the "gameversion" client command will print this plus compile date #define GAMEVERSION "Q2MP4" @@ -65,6 +82,14 @@ #define SPAWNFLAG_NOT_DEATHMATCH 0x00000800 // 2048 #define SPAWNFLAG_NOT_COOP 0x00001000 // 4096 +// Zaero start +// edict->spawnflags2 +// these are set with checkboxes on each entity in the map editor +#define SPAWNFLAG2_MIRRORLEVEL 0x0001 +#define SPAWNFLAG2_NOT_COOP 0x0002 +#define SPAWNFLAG2_NOT_SINGLE 0x0004 +// end Zaero + // edict->flags #define FL_FLY 0x00000001 #define FL_SWIM 0x00000002 // implied immunity to drowining @@ -119,7 +144,9 @@ typedef enum { DAMAGE_NO, DAMAGE_YES, // will take damage if hit - DAMAGE_AIM // auto targeting recognizes this + DAMAGE_AIM, // auto targeting recognizes this + // Zaero + DAMAGE_IMMORTAL // similar to DAMAGE_YES, but health is not deducted } damage_t; typedef enum @@ -149,7 +176,13 @@ typedef enum // Knightmare AMMO_SHOCKSPHERE, AMMO_FUEL, - AMMO_HOMING_ROCKETS + AMMO_HOMING_ROCKETS, + // Zaero (unused for now) + AMMO_FLARES, + AMMO_LASERTRIPBOMB, + AMMO_EMPNUKE, + AMMO_A2K, + AMMO_PLASMASHIELD } ammo_t; @@ -187,10 +220,10 @@ typedef enum #define AI_MEDIC 0x00002000 #define AI_RESURRECTING 0x00004000 #define AI_MANUAL_STEERING 0x00008000 -#define AI_TARGET_ANGER 0x00010000 //Lazarus keep +#define AI_TARGET_ANGER 0x00010000 // Lazarus keep #define AI_DODGING 0x00020000 #define AI_CHARGING 0x00040000 -#define AI_HINT_PATH 0x00080000 //Lazarus keep +#define AI_HINT_PATH 0x00080000 // Lazarus keep #define AI_IGNORE_SHOTS 0x00100000 #define AI_BLOCKED 0x00200000 // used by blocked_checkattack: set to say I'm attacking while blocked // (prevents run-attacks) @@ -209,13 +242,20 @@ typedef enum #define AI_CROUCH 0x40000000 #define AI_EVADE_GRENADE 0x80000000 -//Knightmare- thes are for moreaiflags -#define AI_FREEFORALL 0x00000001 // Set by target_monsterbattle, lets dmgteam monsters +// Knightmare- thes are for aiflags2 +#define AI2_FREEFORALL 0x00000001 // Set by target_monsterbattle, lets dmgteam monsters // attack monsters on opposion dmgteam -#define AI_RANGE_PAUSE 0x00000002 -#define AI_HINT_TEST 0x00000004 +#define AI2_RANGE_PAUSE 0x00000002 +#define AI2_HINT_TEST 0x00000004 +// Zaero +#define AI2_SCHOOLING 0x00000008 +#define AI2_REDUCEDDAMAGE 0x00000010 +#define AI2_DODGETIMEOUT 0x00000020 +#define AI2_MONREDUCEDDAMAGE 0x00000040 +#define AI2_ONESHOTTARGET 0x00000080 +// end Zaero -//Knightmare- monster flags +// Knightmare- monster flags #define MFL_WALK_WALLS 1 #define MFL_DO_NOT_COUNT 2 // set for healed monsters #define MFL_SPAWNED_CARRIER 4 // both do_not_count and spawned are set for spawned monsters @@ -223,7 +263,7 @@ typedef enum #define MFL_SPAWNED_WIDOW 16 // both do_not_count and spawned are set for spawned monsters #define MFL_SPAWNED_MASK 32 // mask to catch all three flavors of spawned -//monster attack state +// monster attack state #define AS_STRAIGHT 1 #define AS_SLIDING 2 #define AS_MELEE 3 @@ -295,7 +335,12 @@ MOVETYPE_RAIN, // identical to MOVETYPE_FLYMISSILE, but doesn't cause splash n MOVETYPE_PENDULUM, // same as MOVETYPE_PUSH, but used only for pendulums to grab special-case MOVETYPE_CONVEYOR, // conveyor -MOVETYPE_SHOCKBOUNCE // Knightmare- added for shockwave +MOVETYPE_SHOCKBOUNCE, // Knightmare- added for shockwave +// Zaero +MOVETYPE_FREEZE, // player freeze, used for Zaero Camera +MOVETYPE_FALLFLOAT, // falls down slopes and floats in water +MOVETYPE_RIDE // basically won't move unless it rides on a MOVETYPE_PUSH entity +// end Zaero } movetype_t; @@ -328,6 +373,7 @@ typedef struct #define IT_XATRIX 0x00000100 // Xatrix item #define IT_ROGUE 0x00000200 // Rogue item #define IT_LAZARUS 0x00000400 // Lazarus item +#define IT_ZAERO 0x00000800 // Zaero item // gitem_t->weapmodel for weapons indicates model index #define WEAP_BLASTER 1 @@ -492,15 +538,15 @@ typedef struct // ROGUE edict_t *disguise_violator; int disguise_violation_framenum; - // ROGUE + // end ROGUE // Lazarus - int fogs; - int trigger_fogs; + int num_fogs; + int num_trigger_fogs; int active_target_fog; int active_fog; int last_active_fog; - fog_t fog; + fog_t current_fog; int flashlight_cost; // cost/10 seconds for flashlight int mud_puddles; int num_3D_sounds; @@ -510,7 +556,11 @@ typedef struct int next_skill; int num_reflectors; qboolean intermission_letterbox; // Knightmare- letterboxing + // end Lazarus + // Zaero + int fadeFrames; + // end Zaero } level_locals_t; @@ -550,7 +600,7 @@ typedef struct vec3_t start_angles; vec3_t end_origin; vec3_t end_angles; - //Knightmare- these are for the bezier curves + // Knightmare- these are for the bezier curves // vec3_t last_pathpoint_origin; // vec3_t last_pathpoint_angles; // vec3_t bezier_begin_point; @@ -606,8 +656,8 @@ typedef struct mmove_t *currentmove; mmove_t *savemove; unsigned int aiflags; // PGM - unsigned, since we're close to the max - unsigned int moreaiflags; //Knightmare- more AI flags, needed for Lazarus stuff - unsigned int monsterflags; //Knightmare- moved some of the Rogue AI flags here + unsigned int aiflags2; // Knightmare- more AI flags, needed for Lazarus stuff + unsigned int monsterflags; // Knightmare- moved some of the Rogue AI flags here int nextframe; float scale; @@ -638,20 +688,20 @@ typedef struct int power_armor_type; int power_armor_power; - //Mappack - array for ai. + // Mappack - array for ai. //vec3_t radial_chk[8]; - //Mappack - for the pathing rountine + // Mappack - for the pathing rountine qboolean following_nodes; - edict_t *target_node; + edict_t *target_node; - //Mappack - for buoy system - edict_t *buoy; + // Mappack - for buoy system + edict_t *buoy; - //Mappack - damit I need one - vec3_t tempvec; + // Mappack - damit I need one + vec3_t tempvec; -//ROGUE +// ROGUE qboolean (*blocked)(edict_t *self, float dist); // edict_t *last_hint; // last hint_path the monster touched float last_hint_time; // last time the monster checked for hintpaths. @@ -682,11 +732,11 @@ typedef struct float quad_framenum; float double_framenum; float invincible_framenum; -//ROGUE +// ROGUE edict_t *leader; edict_t *old_leader; -//ROGUE -//Lazarus +// ROGUE +// Lazarus float min_range; // Monsters stop chasing enemy at this distance float max_range; // Monsters won't notice or attack targets farther than this float ideal_range[2]; // Ideal low and high range from target, weapon-specific @@ -697,7 +747,27 @@ typedef struct int chicken_framenum; int pathdir; // Up/down a hint_path chain flag for medic float visibility; // Ratio of visibility (it's a fog thang) -//end Lazarus +// end Lazarus +// Zaero + int flashTime; + int flashBase; + + // strafing + float flyStrafePitch; + float flyStraanimfeTimeout; + + // schooling info + float zSchoolSightRadius; + float zSchoolMaxSpeed, zSchoolMinSpeed; + float zSpeedStandMax, zSpeedWalkMax; + float zSchoolDecayRate, zSchoolMinimumDistance; + int zSchoolFlags; + + float reducedDamageAmount; + float dodgetimeout; + + vec3_t shottarget; +// end Zaero } monsterinfo_t; // ROGUE @@ -789,18 +859,17 @@ extern int lastgibframe; #define MOD_TRIGGER_HURT 31 #define MOD_HIT 32 #define MOD_TARGET_BLASTER 33 -//Xatrix + +// Xatrix #define MOD_RIPPER 34 #define MOD_PHALANX 35 #define MOD_BRAINTENTACLE 36 #define MOD_BLASTOFF 37 #define MOD_GEKK 38 #define MOD_TRAP 39 -//Xatrix -#define MOD_FRIENDLY_FIRE 0x8000000 +// Xatrix -//======== -//ROGUE +// ROGUE #define MOD_CHAINFIST 40 #define MOD_DISINTEGRATOR 41 #define MOD_ETF_RIFLE 42 @@ -818,9 +887,9 @@ extern int lastgibframe; #define MOD_DOPPLE_EXPLODE 55 #define MOD_DOPPLE_VENGEANCE 56 #define MOD_DOPPLE_HUNTER 57 -//ROGUE -//======== -//Knightmare +// aned ROGUE + +// Knightmare #define MOD_SHOCK_SPHERE 58 #define MOD_SHOCK_SPLASH 59 #define MOD_PROX_SPLASH 60 @@ -832,25 +901,36 @@ extern int lastgibframe; #define MOD_MISSILE 67 #define MOD_MISSILE_SPLASH 68 +// Zaero +#define MOD_SNIPERRIFLE 69 +#define MOD_TRIPBOMB 70 +#define MOD_FLARE 71 +#define MOD_A2K 72 +#define MOD_SONICCANNON 73 +#define MOD_AUTOCANNON 74 +#define MOD_GL_POLYBLEND 75 +// end Zaero + //=============================== // Extra MODs // Quake1 -Skid //=============================== -#define MOD_Q1_AXE 69 -#define MOD_Q1_SG 70 -#define MOD_Q1_SSG 71 -#define MOD_Q1_NG 72 -#define MOD_Q1_SNG 73 -#define MOD_Q1_GL 74 -#define MOD_Q1_RL 75 -#define MOD_Q1_LG 76 -#define MOD_Q1_GL_SPLASH 77 -#define MOD_Q1_RL_SPLASH 78 -#define MOD_Q1_LG_SPLASH 79 -#define MOD_Q1_LASER 80 -#define MOD_Q1_FLAMEBOLT 81 -#define MOD_Q1_FIREPOD 82 +#define MOD_Q1_AXE 76 +#define MOD_Q1_SG 77 +#define MOD_Q1_SSG 78 +#define MOD_Q1_NG 79 +#define MOD_Q1_SNG 80 +#define MOD_Q1_GL 81 +#define MOD_Q1_RL 82 +#define MOD_Q1_LG 83 +#define MOD_Q1_GL_SPLASH 84 +#define MOD_Q1_RL_SPLASH 85 +#define MOD_Q1_LG_SPLASH 86 +#define MOD_Q1_LASER 87 +#define MOD_Q1_FLAMEBOLT 88 +#define MOD_Q1_FIREPOD 89 +#define MOD_FRIENDLY_FIRE 0x8000000 extern int meansOfDeath; @@ -869,6 +949,7 @@ extern cvar_t *maxentities; extern cvar_t *deathmatch; extern cvar_t *coop; extern cvar_t *dmflags; +extern cvar_t *zdmflags; // Zaero added extern cvar_t *skill; extern cvar_t *fraglimit; extern cvar_t *timelimit; @@ -1160,13 +1241,14 @@ void cleanupHealTarget (edict_t *ent); // // g_fog.c // -#define MAX_FOGS 16 +#define MAX_FOGS 64 // was 16 extern fog_t gfogs[MAX_FOGS]; void Cmd_Fog_f (edict_t *ent); -void Fog_Init (); -void Fog (edict_t *ent); //vec3_t viewpoint); -void Fog_Off (qboolean gameShutdown); -void Fog_SetFogParms (); +void Fog_Init (void); +void Fog (edict_t *ent); +void Fog_Off (edict_t *ent); +void Fog_Off_Global (void); +void Fog_SetFogParms (void); // // km_cvar.c @@ -1765,6 +1847,31 @@ typedef struct qboolean HasSpawnFunction(edict_t *ent); int trigger_transition_ents (edict_t *changelevel, edict_t *self); + +// Zaero +// +// z_item.c +// +qboolean EMPNukeCheck(edict_t *ent, vec3_t pos); + +// +// z_weapon.c +// +void fire_bb (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius); +void fire_flare (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage); + +// +// z_ai.c +// +void ai_schoolStand (edict_t *self, float dist); +void ai_schoolRun (edict_t *self, float dist); +void ai_schoolWalk (edict_t *self, float dist); +void ai_schoolCharge (edict_t *self, float dist); +void ai_schoolBackWalk (edict_t *self, float dist); +void ai_schoolSideStepRight (edict_t *self, float dist); +void ai_schoolSideStepLeft (edict_t *self, float dist); +// end Zaero + //============================================================================ // client_t->anim_priority @@ -1820,21 +1927,20 @@ typedef struct qboolean spectator; // client is a spectator -//========= -//ROGUE +// ROGUE int max_tesla; int max_prox; int max_mines; int max_flechettes; int max_disruptors; -//ROGUE -//========= - //Knightmare +// end ROGUE + + // Knightmare added int max_shockspheres; int max_fuel; int max_homing_rockets; - int max_armor; // KM +// int max_armor; // KM qboolean spawn_landmark; qboolean spawn_levelchange; @@ -1848,7 +1954,15 @@ typedef struct int spawn_anim_end; gitem_t *newweapon; + // Zaero + int max_flares; + int max_tbombs; + int max_a2k; + int max_empnuke; + int max_plasmashield; + float visorFrames; + // end Zaero } client_persistant_t; // client data that stays across deathmatch respawns @@ -1970,10 +2084,10 @@ struct gclient_s usercmd_t ucmd; // Lazarus: Copied for convenience in ClientThink int use; // indicates whether +use key is pressed - //Mappack - set when the client is a camera. Change this to a flag + // Mappack - set when the client is a camera. Change this to a flag qboolean incamera; //===================================================== - //Chasecam + // Chasecam //===================================================== int chasetoggle; //whether chasecam is toggled on int chaseactive; //whether chasecam is active @@ -1981,7 +2095,7 @@ struct gclient_s edict_t *oldplayer; //===================================================== - //Misc Timing Vars + // Misc Timing Vars //===================================================== float oldweapon; //Lightning gun, Chainsaw etc @@ -2036,8 +2150,7 @@ struct gclient_s int leftfoot; // 0 or 1, used for footstep sounds int jumping; // 0 or 1, used for jumpkick -//======= -//ROGUE +// ROGUE float double_framenum; float ir_framenum; // float torch_framenum; @@ -2045,8 +2158,30 @@ struct gclient_s float tracker_pain_framenum; edict_t *owned_sphere; // this points to the player's sphere -//ROGUE -//======= +// end ROGUE + +// Zaero + float a2kFramenum; + + // used for blinding + int flashTime; + int flashBase; + + edict_t *zCameraTrack; // the entity to see through + vec3_t zCameraOffset; // offset from camera origin + edict_t *zCameraLocalEntity; + float zCameraStaticFramenum; + + qboolean showOrigin; + + // for sniper rifle + int sniperFramenum; + + // for sonic cannon + float startFireTime; +// end Zaero + + qboolean bfg_missfire; // Knightmare- added for Zaero EMP Nuke }; /* @@ -2196,11 +2331,11 @@ struct edict_s edict_t *prevpath; float speed, accel, decel; - //============= - //Knightmare - int oldmovetype; //backup of movetype - vec3_t relative_velocity; //relative velocity of movewith children - vec3_t relative_avelocity; //relative angular velocity of movewith children + + // Knightmare added + int oldmovetype; // backup of movetype + vec3_t relative_velocity; // relative velocity of movewith children + vec3_t relative_avelocity; // relative angular velocity of movewith children vec3_t movewith_offset; vec3_t old_offset; int movewith_set; @@ -2210,7 +2345,7 @@ struct edict_s float width; float length; float side; - vec3_t origin_offset; //These are from Lazarus for the rider code + vec3_t origin_offset; // These are from Lazarus for the rider code vec3_t org_angles; vec3_t org_mins; vec3_t org_maxs; @@ -2236,14 +2371,12 @@ struct edict_s edict_t *crane_light; vec_t crane_bonk; - //Knightmare - //============= vec3_t movedir; vec3_t pos1, pos2; - vec3_t pos0; //Knightmare- initial position for secret doors + vec3_t pos0; // Knightmare- initial position for secret doors vec3_t velocity; - vec3_t oldvelocity; //Knightmare added + vec3_t oldvelocity; // Knightmare added vec3_t avelocity; int mass; float density; @@ -2262,7 +2395,8 @@ struct edict_s edict_t *goalentity; edict_t *movetarget; - //Knightmare- rotating train stuff + + // Knightmare- rotating train stuff float pitch_speed; float yaw_speed; float roll_speed; @@ -2312,8 +2446,8 @@ struct edict_s float nextthink; void (*prethink) (edict_t *ent); void (*think)(edict_t *self); - void (*postthink) (edict_t *ent); //Knightmare added - void (*blocked)(edict_t *self, edict_t *other); //move to moveinfo? + void (*postthink) (edict_t *ent); // Knightmare added + void (*blocked)(edict_t *self, edict_t *other); // move to moveinfo? void (*touch)(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf); void (*use)(edict_t *self, edict_t *other, edict_t *activator); void (*pain)(edict_t *self, edict_t *other, float kick, int damage); @@ -2326,9 +2460,9 @@ struct edict_s float damage_debounce_time; float gravity_debounce_time; // used by item_ movement commands to prevent // monsters from dropping to floor - float fly_sound_debounce_time; //move to clientinfo + float fly_sound_debounce_time; // move to clientinfo float last_move_time; - float last_fire_time; //Knightmare added + float last_fire_time; // Knightmare added int health; int max_health; @@ -2434,7 +2568,7 @@ struct edict_s // should be forced to a good value for fog obscuration // of HOM - //Mappack - for ridahs controllable turret (but beels weapon thing) + // Mappack - for ridahs controllable turret (but beels weapon thing) edict_t *turret; //ugly ? edict_t *child; // "real" infantry guy, child of remote turret_driver @@ -2457,8 +2591,8 @@ struct edict_s char *movewith; char *dmgteam; // for target_monsterbattle int do_not_rotate; // whether to movewith rotate a func_door -//========= -//ROGUE + +// ROGUE int plat2flags; vec3_t offset; vec3_t gravityVector; @@ -2469,8 +2603,60 @@ struct edict_s int hint_chain_id; // FIXME - debug help! float lastMoveTime; -//ROGUE -//========= +// end ROGUE + +// Zaero + char *model2; + char *model3; + char *model4; + + float aspeed; + + // can use this for misc. timeouts + float timeout; + +// int blood_type; // specifies blood effect + + // for func_door, also used by monster_autocannon, and misc_securitycamera + int active; + int seq; + + // between level saves/loads + int spawnflags2; + int oldentnum; + + // titan laser + edict_t *laser; + + float weaponsound_time; + + // schooling info + edict_t *zRaduisList, *zSchoolChain; + float zDistance; + + // this is for MOVETYPE_RIDE + edict_t *rideWith[2]; + vec3_t rideWithOffset[2]; + + // camera number + vec3_t mangle; + + // time left for the visor (stored if a visor is dropped) + int visorFrames; + + // monster team + char *mteam; + + // for random func_timer targets +// char targets[16][MAX_QPATH]; +// int numTargets; + + // used by floor-mounted autocannon + int onFloor; + + float bossFireTimeout; + int bossFireCount; +// end Zaero }; //============= @@ -2550,3 +2736,7 @@ int DBall_CheckDMRules (void); #define FLASHLIGHT_USE POWERUP_NEW_ENT #define FLASHLIGHT_DRAIN 60 #define FLASHLIGHT_ITEM "Cells" + +// Zaero dmflags +#define ZDM_NO_GL_POLYBLEND_DAMAGE 1 +#define ZDM_ZAERO_ITEMS 2 diff --git a/missionpack/g_main.c b/missionpack/g_main.c index bfc0f56..a6e25f1 100644 --- a/missionpack/g_main.c +++ b/missionpack/g_main.c @@ -16,6 +16,7 @@ edict_t *g_edicts; cvar_t *deathmatch; cvar_t *coop; cvar_t *dmflags; +cvar_t *zdmflags; // Zaero added cvar_t *skill; cvar_t *fraglimit; cvar_t *timelimit; @@ -151,9 +152,12 @@ void ShutdownGame (void) //gi.cvar_forceset("cd_loopcount", va("%d",lazarus_cd_loop->value)); //gi.cvar_forceset("gl_clear", va("%d", lazarus_gl_clear->value)); } + // Lazarus: Turn off fog if it's on - if (!dedicated->value) - Fog_Off (true); + if (!dedicated->value) { + // Fog_Off (true); + Fog_Off_Global (); + } // and shut down FMOD FMOD_Shutdown(); @@ -340,6 +344,7 @@ edict_t *CreateTargetChangeLevel(char *map) ent->classname = "target_changelevel"; Com_sprintf(level.nextmap, sizeof(level.nextmap), "%s", map); ent->map = level.nextmap; + ent->spawnflags2 = 0; // Zaero added return ent; } diff --git a/missionpack/g_misc.c b/missionpack/g_misc.c index aec021e..28a59ba 100644 --- a/missionpack/g_misc.c +++ b/missionpack/g_misc.c @@ -2564,14 +2564,14 @@ void SP_misc_viper (edict_t *ent) ent->movetype = MOVETYPE_PUSH; ent->solid = SOLID_NOT; - //Mappack - if(ent->spawnflags & 2) + // Mappack + if (ent->spawnflags & 2) { ent->solid = SOLID_BBOX; ent->s.modelindex = gi.modelindex ("models/ships/bigviper/tris.md2"); VectorSet (ent->mins, -176, -120, -24); VectorSet (ent->maxs, 176, 120, 72); - } //Mappack + } // Mappack else { ent->s.modelindex = gi.modelindex ("models/ships/viper/tris.md2"); diff --git a/missionpack/g_mmove_decs.h b/missionpack/g_mmove_decs.h index c54ccf8..aea00c7 100644 --- a/missionpack/g_mmove_decs.h +++ b/missionpack/g_mmove_decs.h @@ -30,6 +30,37 @@ extern mmove_t hound_move_walk ; extern mmove_t hound_move_run ; extern mmove_t hound_stand2 ; extern mmove_t hound_stand1 ; +extern mmove_t handler_move_attack1 ; +extern mmove_t handler_stand5 ; +extern mmove_t handler_stand4 ; +extern mmove_t handler_stand3 ; +extern mmove_t handler_stand2 ; +extern mmove_t handler_stand1 ; +extern mmove_t zboss_move_death2 ; +extern mmove_t zboss_move_death1 ; +extern mmove_t zboss_move_c2h ; +extern mmove_t zboss_move_h2c ; +extern mmove_t zboss_move_postcannon ; +extern mmove_t zboss_move_precannon ; +extern mmove_t zboss_move_attack3 ; +extern mmove_t zboss_move_prehook ; +extern mmove_t zboss_move_posthook ; +extern mmove_t zboss_move_attack2a ; +extern mmove_t zboss_move_attack2b ; +extern mmove_t zboss_move_attack1a ; +extern mmove_t zboss_move_attack1b ; +extern mmove_t zboss_move_premelee ; +extern mmove_t zboss_move_attack2c ; +extern mmove_t zboss_move_pain3 ; +extern mmove_t zboss_move_pain2 ; +extern mmove_t zboss_move_pain1 ; +extern mmove_t zboss_move_run ; +extern mmove_t zboss_move_prerun ; +extern mmove_t zboss_move_walk ; +extern mmove_t zboss_move_prewalk ; +extern mmove_t zboss_move_postwalk ; +extern mmove_t zboss_stand2 ; +extern mmove_t zboss_stand1 ; extern mmove_t widow2_move_really_dead ; extern mmove_t widow2_move_dead ; extern mmove_t widow2_move_death ; diff --git a/missionpack/g_mmove_list.h b/missionpack/g_mmove_list.h index 65de6e7..9ce6f6c 100644 --- a/missionpack/g_mmove_list.h +++ b/missionpack/g_mmove_list.h @@ -30,6 +30,37 @@ {"hound_move_run", &hound_move_run}, {"hound_stand2", &hound_stand2}, {"hound_stand1", &hound_stand1}, +{"handler_move_attack1", &handler_move_attack1}, +{"handler_stand5", &handler_stand5}, +{"handler_stand4", &handler_stand4}, +{"handler_stand3", &handler_stand3}, +{"handler_stand2", &handler_stand2}, +{"handler_stand1", &handler_stand1}, +{"zboss_move_death2", &zboss_move_death2}, +{"zboss_move_death1", &zboss_move_death1}, +{"zboss_move_c2h", &zboss_move_c2h}, +{"zboss_move_h2c", &zboss_move_h2c}, +{"zboss_move_postcannon", &zboss_move_postcannon}, +{"zboss_move_precannon", &zboss_move_precannon}, +{"zboss_move_attack3", &zboss_move_attack3}, +{"zboss_move_prehook", &zboss_move_prehook}, +{"zboss_move_posthook", &zboss_move_posthook}, +{"zboss_move_attack2a", &zboss_move_attack2a}, +{"zboss_move_attack2b", &zboss_move_attack2b}, +{"zboss_move_attack1a", &zboss_move_attack1a}, +{"zboss_move_attack1b", &zboss_move_attack1b}, +{"zboss_move_premelee", &zboss_move_premelee}, +{"zboss_move_attack2c", &zboss_move_attack2c}, +{"zboss_move_pain3", &zboss_move_pain3}, +{"zboss_move_pain2", &zboss_move_pain2}, +{"zboss_move_pain1", &zboss_move_pain1}, +{"zboss_move_run", &zboss_move_run}, +{"zboss_move_prerun", &zboss_move_prerun}, +{"zboss_move_walk", &zboss_move_walk}, +{"zboss_move_prewalk", &zboss_move_prewalk}, +{"zboss_move_postwalk", &zboss_move_postwalk}, +{"zboss_stand2", &zboss_stand2}, +{"zboss_stand1", &zboss_stand1}, {"widow2_move_really_dead", &widow2_move_really_dead}, {"widow2_move_dead", &widow2_move_dead}, {"widow2_move_death", &widow2_move_death}, diff --git a/missionpack/g_monster.c b/missionpack/g_monster.c index 4d7fcec..2448fa1 100644 --- a/missionpack/g_monster.c +++ b/missionpack/g_monster.c @@ -917,7 +917,7 @@ void monster_use (edict_t *self, edict_t *other, edict_t *activator) // if monster is "used" by player, turn off good guy stuff if (activator->client) - { //Knightmare- gekks and stalkers use different spawnflag + { // Knightmare- gekks and stalkers use different spawnflag if (UseSpecialGoodGuyFlag(self)) self->spawnflags &= ~16; else if (UseRegularGoodGuyFlag(self)) @@ -951,7 +951,7 @@ void monster_triggered_spawn (edict_t *self) // Knightmare- teleport effect for Q1 monsters if (self->flags & FL_Q1_MONSTER) { #ifdef KMQUAKE2_ENGINE_MOD - self->s.event = EV_PLAYER_TELEPORT_Q1; + self->s.event = EV_PLAYER_TELEPORT2; #else self->s.event = EV_PLAYER_TELEPORT; Q1TeleportSounds(self); @@ -1496,20 +1496,22 @@ int PatchMonsterModel (char *modelname) byte *data; // model data int datasize; // model data size (bytes) int newoffset; // model data offset (after skins) - qboolean is_tank=false; - qboolean is_soldier=false; - //Knightmare added - qboolean is_brain=false; - qboolean is_gekk=false; - qboolean is_fixbot=false; - qboolean is_chick=false; - qboolean is_soldierh=false; - qboolean is_carrier=false; - qboolean is_hover=false; - qboolean is_medic=false; - qboolean is_turret=false; + qboolean is_tank = false; + qboolean is_soldier = false; + // Knightmare added + qboolean is_brain = false; + qboolean is_gekk = false; + qboolean is_fixbot = false; + qboolean is_chick = false; + qboolean is_soldierh = false; + qboolean is_carrier = false; + qboolean is_hover = false; + qboolean is_medic = false; + qboolean is_turret = false; + qboolean is_zboss_mech = false; + qboolean is_zboss_pilot = false; - qboolean gamedirpakfile=false; + qboolean gamedirpakfile = false; // get game (moddir) name gamedir = gi.cvar("game", "", 0); @@ -1589,7 +1591,18 @@ int PatchMonsterModel (char *modelname) is_turret = true; numskins = 12; } - //end Knightmare + else if (!strcmp(modelname,"models/monsters/bossz/mech/tris.md2")) + { + is_zboss_mech = true; + numskins = 12; + } + else if (!strcmp(modelname,"models/monsters/bossz/pilot/tris.md2")) + { + is_zboss_pilot = true; + numskins = 12; + } + + // end Knightmare for (j=0; jdmgteam); while(grouchmate) { - grouchmate->monsterinfo.moreaiflags |= AI_FREEFORALL; + grouchmate->monsterinfo.aiflags2 |= AI2_FREEFORALL; grouchmate = G_Find(grouchmate,FOFS(dmgteam),grouch->dmgteam); } } @@ -242,7 +242,7 @@ void use_target_monsterbattle(edict_t *self, edict_t *other, edict_t *activator) targetmate = G_Find(NULL,FOFS(dmgteam),target->dmgteam); while(targetmate) { - targetmate->monsterinfo.moreaiflags |= AI_FREEFORALL; + targetmate->monsterinfo.aiflags2 |= AI2_FREEFORALL; targetmate = G_Find(targetmate,FOFS(dmgteam),target->dmgteam); } } diff --git a/missionpack/g_phys.c b/missionpack/g_phys.c index bcd0632..90441b9 100644 --- a/missionpack/g_phys.c +++ b/missionpack/g_phys.c @@ -2788,6 +2788,166 @@ void SV_Physics_Conveyor(edict_t *ent) } +void SV_Physics_FallFloat (edict_t *ent) +{ + float gravVal = ent->gravity * sv_gravity->value * FRAMETIME; + qboolean wasonground = false; + qboolean hitsound = false; + + // check velocity + SV_CheckVelocity (ent); + + wasonground = (ent->groundentity == NULL); + if (ent->velocity[2] < sv_gravity->value*-0.1) + hitsound = true; + + if (!ent->waterlevel) + { + vec3_t min, max; + trace_t tr; + vec3_t end; + vec3_t normal; + vec3_t gravity; + + VectorCopy(ent->mins, min); + VectorCopy(ent->maxs, max); + + VectorCopy(ent->s.origin, end); + end[2] -= 0.25; // down 4 + + tr = gi.trace(ent->s.origin, min, max, end, ent, MASK_SHOT); + if (tr.plane.normal[2] > 0.7) // on solid ground + { + ent->groundentity = tr.ent; + VectorCopy(tr.endpos, ent->s.origin); + VectorSet(ent->velocity, 0, 0, 0); + } + else if (tr.fraction < 1.0 && tr.plane.normal[2] <= 0.7) // on steep slope + { + VectorCopy(tr.plane.normal, normal); + VectorSet(gravity, 0, 0, -gravVal); + VectorMA(gravity, gravVal, normal, ent->velocity); + ent->groundentity = NULL; + } + else // in freefall + { + ent->velocity[2] -= gravVal; + ent->groundentity = NULL; + } + } + else + //if (ent->waterlevel) + { + // where's the midpoint? above or below the water? + const double WATER_MASS = 500.0; + vec3_t accel; + double percentBelow = 0.0; + double massOfObject = 0.0; + double massOfVolumeWater = 0.0; + double massOfWater = 0.0; + double massDiff = 0.0; + double i = 0.0; + vec3_t volume; + + // TODO if we're not grounded on the bottom of the lake... + + // calculate massPerCubicMetre + VectorScale(ent->size, 1.0/32.0, volume); + massOfObject = ent->mass; + massOfVolumeWater = WATER_MASS * (volume[0] * volume[1] * volume[2]); + + // how much of ourself is actually in the water? + percentBelow = 1.0; + for (i = 0.0; i <= 1.0; i += 0.05) + { + vec3_t midpoint; + int watertype; + + VectorAdd(ent->s.origin, ent->mins, midpoint); + VectorMA(midpoint, i, ent->maxs, midpoint); + watertype = gi.pointcontents (midpoint); + + if (!(watertype & MASK_WATER)) + { + percentBelow = i - 0.05; + break; + } + } + if (percentBelow < 0.05) // safety net + percentBelow = 0.0; + massOfWater = percentBelow * massOfVolumeWater; + massDiff = massOfWater - massOfObject; // difference between + VectorClear(accel); + VectorSet(accel, 0, 0, gravVal * (massDiff / massOfVolumeWater)); + VectorScale(ent->velocity, 0.7, ent->velocity); + if (VectorLength(accel) > 4) + VectorAdd(ent->velocity, accel, ent->velocity); + } + + if (ent->velocity[0] || ent->velocity[1] || ent->velocity[2]) + { + qboolean isinwater = false; + qboolean wasinwater = false; + vec3_t old_origin; + VectorCopy (ent->s.origin, old_origin); + + SV_FlyMove (ent, FRAMETIME, MASK_SHOT); + + gi.linkentity (ent); + G_TouchTriggers (ent); + + if (ent->groundentity) + if (!wasonground) + if (hitsound) + gi.sound (ent, 0, gi.soundindex("world/land.wav"), 1, 1, 0); + + // check for water transition + wasinwater = (ent->watertype & MASK_WATER); + ent->watertype = gi.pointcontents (ent->s.origin); + isinwater = ent->watertype & MASK_WATER; + + if (isinwater) + ent->waterlevel = 1; + else + ent->waterlevel = 0; + + if (!wasinwater && isinwater) + gi.positioned_sound (old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); + else if (wasinwater && !isinwater) + gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); + + } + + // relink + gi.linkentity(ent); + + // regular thinking + SV_RunThink (ent); +} + + +void adjustRiders(edict_t *ent) +{ + int i = 0; + + // make sure the offsets are constant + for (i = 0; i < 2; i++) + { + if (ent->rideWith[i] != NULL) + VectorAdd(ent->s.origin, ent->rideWithOffset[i], ent->rideWith[i]->s.origin); + } +} + + +void SV_Physics_Ride (edict_t *ent) +{ + // base ourself on the step + SV_Physics_Step(ent); + + adjustRiders(ent); +} + + //============================================================================ /* ================ @@ -2805,7 +2965,7 @@ void G_RunEntity (edict_t *ent) if (level.freeze && Q_stricmp(ent->classname,"chasecam")) return; - if(ent->movetype == MOVETYPE_STEP) + if (ent->movetype == MOVETYPE_STEP) VectorCopy(ent->s.origin, previous_origin); //PGM @@ -2854,18 +3014,26 @@ void G_RunEntity (edict_t *ent) break; // Lazarus case MOVETYPE_WALK: - SV_Physics_None(ent); + SV_Physics_None (ent); break; case MOVETYPE_CONVEYOR: - SV_Physics_Conveyor(ent); + SV_Physics_Conveyor (ent); break; + // Zaero + case MOVETYPE_FALLFLOAT: + SV_Physics_FallFloat (ent); + break; + case MOVETYPE_RIDE: + SV_Physics_Ride (ent); + break; + // end Zaero default: gi.error ("SV_Physics: bad movetype %i", (int)ent->movetype); } //PGM - if(ent->movetype == MOVETYPE_STEP) + if (ent->movetype == MOVETYPE_STEP) { // if we moved, check and fix origin if needed if (!VectorCompare(ent->s.origin, previous_origin)) diff --git a/missionpack/g_save.c b/missionpack/g_save.c index c998473..a4a8e0f 100644 --- a/missionpack/g_save.c +++ b/missionpack/g_save.c @@ -103,7 +103,7 @@ field_t fields[] = { #endif {"aiflags", FOFS(monsterinfo.aiflags), F_INT}, - {"moreaiflags", FOFS(monsterinfo.moreaiflags), F_INT}, + {"aiflags2", FOFS(monsterinfo.aiflags2), F_INT}, {"goalentity", FOFS(goalentity), F_EDICT, FFL_NOSPAWN}, {"movetarget", FOFS(movetarget), F_EDICT, FFL_NOSPAWN}, {"enemy", FOFS(enemy), F_EDICT, FFL_NOSPAWN}, @@ -157,7 +157,7 @@ field_t fields[] = { {"phase", STOFS(phase), F_FLOAT, FFL_SPAWNTEMP}, {"shift", STOFS(shift), F_FLOAT, FFL_SPAWNTEMP}, -//need for item field in edict struct, FFL_SPAWNTEMP item will be skipped on saves + // need for item field in edict struct, FFL_SPAWNTEMP item will be skipped on saves {"item", FOFS(item), F_ITEM}, {"gravity", STOFS(gravity), F_LSTRING, FFL_SPAWNTEMP}, @@ -302,6 +302,40 @@ field_t fields[] = { // {"sidestep", FOFS(monsterinfo.sidestep), F_MMOVE, FFL_NOSPAWN}, // ROGUE + // Zaero + {"model2", FOFS(model2), F_LSTRING}, + {"model3", FOFS(model3), F_LSTRING}, + {"model4", FOFS(model4), F_LSTRING}, + + {"aspeed", FOFS(aspeed), F_FLOAT}, + {"timeout", FOFS(timeout), F_FLOAT}, + {"active", FOFS(active), F_INT}, + {"seq", FOFS(seq), F_INT}, + {"spawnflags2", FOFS(spawnflags2), F_INT}, + {"oldentnum", FOFS(oldentnum), F_INT}, + {"laser", FOFS(laser), F_EDICT, FFL_NOSPAWN}, + {"weaponsound_time", FOFS(weaponsound_time), F_FLOAT}, + + {"zRaduisList", FOFS(zRaduisList), F_EDICT, FFL_NOSPAWN}, + {"zSchoolChain", FOFS(zSchoolChain), F_EDICT, FFL_NOSPAWN}, + {"zDistance", FOFS(zDistance), F_FLOAT}, + + {"rideWith0", FOFS(rideWith[0]), F_EDICT, FFL_NOSPAWN}, + {"rideWith1", FOFS(rideWith[1]), F_EDICT, FFL_NOSPAWN}, + {"rideWithOffset0", FOFS(rideWithOffset[0]), F_VECTOR}, + {"rideWithOffset1", FOFS(rideWithOffset[1]), F_VECTOR}, + + {"mangle", FOFS(mangle), F_VECTOR}, + {"visorFrames", FOFS(visorFrames), F_INT}, + {"mteam", FOFS(mteam), F_LSTRING}, + {"onFloor", FOFS(onFloor), F_INT}, + {"bossFireTimeout", FOFS(bossFireTimeout), F_FLOAT}, + {"bossFireCount", FOFS(bossFireCount), F_INT}, + + {"mirrortarget", 0, F_IGNORE}, + {"mirrorlevelsave", 0, F_IGNORE}, + // end Zaero + {0, 0, 0, 0} }; @@ -319,6 +353,9 @@ field_t levelfields[] = {"disguise_violator", LLOFS(disguise_violator), F_EDICT}, // ROGUE + // Knightmare added + {"current_fog_ent", LLOFS(current_fog.ent), F_EDICT}, + {NULL, 0, F_INT} }; @@ -329,13 +366,17 @@ field_t clientfields[] = {"newweapon", CLOFS(newweapon), F_ITEM}, // ROGUE {"owned_sphere", CLOFS(owned_sphere), F_EDICT}, - // ROGUE - //Knightmare + // end ROGUE + // Knightmare {"chasecam", CLOFS(chasecam), F_EDICT}, {"oldplayer", CLOFS(oldplayer), F_EDICT}, {"push", CLOFS(push), F_EDICT}, {"spycam", CLOFS(spycam), F_EDICT}, {"homing_rocket", CLOFS(homing_rocket), F_EDICT}, + // Zaero + {"zCameraTrack", CLOFS(zCameraTrack), F_EDICT}, + {"zCameraLocalEntity", CLOFS(zCameraLocalEntity), F_EDICT}, + // end Zaero {NULL, 0, F_INT} }; @@ -397,6 +438,7 @@ void InitGame (void) // change anytime vars dmflags = gi.cvar ("dmflags", "0", CVAR_SERVERINFO); + zdmflags = gi.cvar ("zdmflags", "0", CVAR_SERVERINFO); // Zaero added fraglimit = gi.cvar ("fraglimit", "0", CVAR_SERVERINFO); timelimit = gi.cvar ("timelimit", "0", CVAR_SERVERINFO); password = gi.cvar ("password", "", CVAR_USERINFO); diff --git a/missionpack/g_spawn.c b/missionpack/g_spawn.c index 937ecd6..ae7aec3 100644 --- a/missionpack/g_spawn.c +++ b/missionpack/g_spawn.c @@ -176,9 +176,20 @@ void SP_monster_boss5 (edict_t *self); // Zaero void SP_monster_hound (edict_t *self); +void SP_monster_handler (edict_t *self); void SP_monster_sentien(edict_t *self); +void SP_monster_zboss (edict_t *self); +void SP_target_zboss_target(edict_t *self); +void SP_func_barrier(edict_t *self); +void SP_trigger_laser(edict_t *self); +void SP_misc_commdish (edict_t *self); +void SP_misc_crate(edict_t *self); +void SP_misc_crate_medium(edict_t *self); +void SP_misc_crate_small(edict_t *self); +void SP_misc_seat(edict_t *self); +// end Zaero -//Knightmare- the dog from Coconut Monkey 3 +// Knightmare- the dog from Coconut Monkey 3 void SP_monster_dog (edict_t *self); void SP_rotating_light (edict_t *self); @@ -532,7 +543,7 @@ spawn_t spawns[] = { // END 14-APR-98 // RAFAEL 12-MAY-98 - //Rogue monsters + // Rogue monsters {"monster_daedalus", SP_monster_hover}, {"monster_medic_commander", SP_monster_medic}, {"monster_stalker", SP_monster_stalker}, @@ -544,9 +555,20 @@ spawn_t spawns[] = { // Zaero {"monster_hound", SP_monster_hound}, + {"monster_handler", SP_monster_handler}, {"monster_sentien", SP_monster_sentien}, + {"monster_zboss", SP_monster_zboss}, + {"target_zboss_target", SP_target_zboss_target}, + {"func_barrier", SP_func_barrier}, + {"trigger_laser", SP_trigger_laser}, + {"misc_commdish", SP_misc_commdish}, + {"misc_crate", SP_misc_crate}, + {"misc_crate_medium", SP_misc_crate_medium}, + {"misc_crate_small", SP_misc_crate_small}, + {"misc_seat", SP_misc_seat}, + // end Zaero - //Knightmare- the dog from Coconut Monkey 3 + // Knightmare- the dog from Coconut Monkey 3 {"monster_dog", SP_monster_dog}, {"misc_nuke", SP_misc_nuke}, @@ -771,7 +793,7 @@ void ED_CallSpawn (edict_t *ent) // replace brains in Reckoning gamedir = gi.cvar("game", "", 0); - if (*gamedir->string && !Q_stricmp(gamedir->string, "xatrix") + if (gamedir->string && !Q_stricmp(gamedir->string, "xatrix") && IsXatrixMap() && !strcmp(ent->classname, "monster_brain")) ent->classname = "monster_brain_beta"; @@ -1609,6 +1631,7 @@ void SpawnEntities (char *mapname, char *entities, char *spawnpoint) ent = g_edicts; else ent = G_Spawn (); + ent->spawnflags2 = 0; // Zaero added entities = ED_ParseEdict (entities, ent); // yet another map hack @@ -1630,7 +1653,7 @@ void SpawnEntities (char *mapname, char *entities, char *spawnpoint) { if (deathmatch->value) { - if ( ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH ) + if (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH) { G_FreeEdict (ent); inhibit++; @@ -1982,6 +2005,7 @@ void SP_worldspawn (edict_t *ent) ent->solid = SOLID_BSP; ent->inuse = true; // since the world doesn't use G_Spawn() ent->s.modelindex = 1; // world model is always index 1 + ent->spawnflags2 = 0; // Zaero added //--------------- @@ -2102,9 +2126,9 @@ void SP_worldspawn (edict_t *ent) gi.modelindex ("#w_phalanx.md2"); // Knightmare added gi.modelindex ("#w_ripper.md2"); // Knightmare added gi.modelindex ("#w_shockwave.md2"); // Knightmare added -// gi.modelindex ("#a_trap.md2"); // Knightmare added -// gi.modelindex ("#a_tesla.md2"); // Knightmare added -// gi.modelindex ("#w_grapple.md2"); + // gi.modelindex ("#a_trap.md2"); // Knightmare added + // gi.modelindex ("#a_tesla.md2"); // Knightmare added + // gi.modelindex ("#w_grapple.md2"); } //------------------- @@ -2119,24 +2143,24 @@ void SP_worldspawn (edict_t *ent) gi.soundindex ("mud/mud_in2.wav"); // feet hitting mud gi.soundindex ("mud/mud_out1.wav"); // feet leaving mud gi.soundindex ("mud/mud_un1.wav"); // head going under mud - //gi.soundindex ("mud/wade_mud1.wav"); - //gi.soundindex ("mud/wade_mud2.wav"); +// gi.soundindex ("mud/wade_mud1.wav"); +// gi.soundindex ("mud/wade_mud2.wav"); - //Knightmare- moved these precaches to item data blocks - //gi.soundindex ("player/u_breath1.wav"); - //gi.soundindex ("player/u_breath2.wav"); + // Knightmare- moved these precaches to item data blocks +// gi.soundindex ("player/u_breath1.wav"); +// gi.soundindex ("player/u_breath2.wav"); gi.soundindex ("items/pkup.wav"); // bonus item pickup gi.soundindex ("world/land.wav"); // landing thud gi.soundindex ("misc/h2ohit1.wav"); // landing splash - //gi.soundindex ("items/damage.wav"); +// gi.soundindex ("items/damage.wav"); // ROGUE - double damage - //gi.soundindex ("misc/ddamage1.wav"); +// gi.soundindex ("misc/ddamage1.wav"); // rogue - //gi.soundindex ("items/protect.wav"); - //gi.soundindex ("items/protect4.wav"); +// gi.soundindex ("items/protect.wav"); +// gi.soundindex ("items/protect4.wav"); gi.soundindex ("weapons/noammo.wav"); // Knightmare- does this even get used in deathmatch? @@ -2154,22 +2178,22 @@ void SP_worldspawn (edict_t *ent) // Fog clipping - if "fogclip" is non-zero, force gl_clear to a good // value for obscuring HOM with fog... "good" is driver-dependent - if(ent->fogclip) + if (ent->fogclip) { - if(gl_driver && !Q_stricmp(gl_driver->string,"3dfxgl")) + if ( gl_driver && !Q_stricmp(gl_driver->string, "3dfxgl") ) gi.cvar_forceset("gl_clear", "0"); else gi.cvar_forceset("gl_clear", "1"); } // FMOD 3D sound attenuation: - if(ent->attenuation <= 0.) + if (ent->attenuation <= 0.) ent->attenuation = 1.0; // FMOD 3D sound Doppler shift: - if(st.shift > 0) + if (st.shift > 0) ent->moveinfo.distance = st.shift; - else if(st.shift < 0) + else if (st.shift < 0) ent->moveinfo.distance = 0.0; else ent->moveinfo.distance = 1.0; diff --git a/missionpack/g_trigger.c b/missionpack/g_trigger.c index 633e3e8..3692058 100644 --- a/missionpack/g_trigger.c +++ b/missionpack/g_trigger.c @@ -341,9 +341,9 @@ void trigger_key_use (edict_t *self, edict_t *other, edict_t *activator) { int index; - if (!self->item) + if (!self || !self->item) return; - if (!activator->client) + if (!activator || !activator->client) return; index = ITEM_INDEX(self->item); @@ -355,7 +355,7 @@ void trigger_key_use (edict_t *self, edict_t *other, edict_t *activator) if (!(self->spawnflags & 4)) { if (self->key_message && strlen(self->key_message)) - gi.centerprintf (activator, self->key_message); + gi.centerprintf (activator, "%s", self->key_message); else gi.centerprintf (activator, "You need the %s", self->item->pickup_name); // Skid added @@ -363,10 +363,10 @@ void trigger_key_use (edict_t *self, edict_t *other, edict_t *activator) { if (index == key_q1_med_gold_index || index == key_q1_med_silver_index) gi.sound (activator, CHAN_AUTO, gi.soundindex ("q1world/doors/medtry.wav"), 1, ATTN_NORM, 0); + else if (index == key_q1_rune_gold_index || index == key_q1_rune_silver_index) + gi.sound (activator, CHAN_AUTO, gi.soundindex ("q1world/doors/runetry.wav"), 1, ATTN_NORM, 0); else if (index == key_q1_base_gold_index || index == key_q1_base_silver_index) gi.sound (activator, CHAN_AUTO, gi.soundindex ("q1world/doors/basetry.wav"), 1, ATTN_NORM, 0); - else - gi.sound (activator, CHAN_AUTO, gi.soundindex ("q1world/doors/runetry.wav"), 1, ATTN_NORM, 0); } else // end Skid @@ -382,10 +382,10 @@ void trigger_key_use (edict_t *self, edict_t *other, edict_t *activator) { if (index == key_q1_med_gold_index || index == key_q1_med_silver_index) gi.sound (activator, CHAN_AUTO, gi.soundindex ("q1world/doors/meduse.wav"), 1, ATTN_NORM, 0); + else if (index == key_q1_rune_gold_index || index == key_q1_rune_silver_index) + gi.sound (activator, CHAN_AUTO, gi.soundindex ("q1world/doors/runeuse.wav"), 1, ATTN_NORM, 0); else if (index == key_q1_base_gold_index || index == key_q1_base_silver_index) gi.sound (activator, CHAN_AUTO, gi.soundindex ("q1world/doors/baseuse.wav"), 1, ATTN_NORM, 0); - else - gi.sound (activator, CHAN_AUTO, gi.soundindex ("q1world/doors/runeuse.wav"), 1, ATTN_NORM, 0); } else // end Skid @@ -510,7 +510,7 @@ If NoMessage is not set, it will print "1 more...2 more..." etc, when triggered "count" triggers before firing; default=2 */ -void trigger_counter_use(edict_t *self, edict_t *other, edict_t *activator) +void trigger_counter_use (edict_t *self, edict_t *other, edict_t *activator) { if (self->count == 0) return; diff --git a/missionpack/g_utils.c b/missionpack/g_utils.c index 48808f2..d187e0f 100644 --- a/missionpack/g_utils.c +++ b/missionpack/g_utils.c @@ -1435,7 +1435,7 @@ qboolean CheckCoop_MapHacks (edict_t *ent) } -//Knightmare added +// Knightmare added /* ==================== UseSpecialGoodGuyFlag @@ -1451,13 +1451,14 @@ qboolean UseSpecialGoodGuyFlag (edict_t *monster) return false; if (!strcmp(monster->classname, "monster_gekk") - || !strcmp(monster->classname, "monster_stalker")) + || !strcmp(monster->classname, "monster_stalker") + || !strcmp(monster->classname, "monster_handler")) return true; return false; } -//Knightmare added +// Knightmare added /* ==================== UseRegularGoodGuyFlag @@ -1475,7 +1476,8 @@ qboolean UseRegularGoodGuyFlag (edict_t *monster) if (strcmp(monster->classname, "monster_gekk") && strcmp(monster->classname, "monster_stalker") && strcmp(monster->classname, "monster_turret") - && strcmp(monster->classname, "monster_fixbot")) + && strcmp(monster->classname, "monster_fixbot") + && strcmp(monster->classname, "monster_handler")) return true; return false; diff --git a/missionpack/g_weapon_q1.c b/missionpack/g_weapon_q1.c index a8819c3..5fff92b 100644 --- a/missionpack/g_weapon_q1.c +++ b/missionpack/g_weapon_q1.c @@ -603,27 +603,27 @@ void q1_fire_lightning (edict_t *self, vec3_t start, vec3_t dir, int damage) // trace 2 tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT); - if(self->client->chasetoggle) + if (self->client->chasetoggle) { gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_MEDIC_CABLE_ATTACK); -// gi.WriteByte (TE_HEATBEAM); + // gi.WriteByte (TE_HEATBEAM); gi.WriteShort (self->client->oldplayer - g_edicts); gi.WritePosition (start); gi.WritePosition (tr.endpos); gi.multicast (self->client->oldplayer->s.origin, MULTICAST_PVS); -// gi.multicast (self->client->oldplayer->s.origin, MULTICAST_ALL); + // gi.multicast (self->client->oldplayer->s.origin, MULTICAST_ALL); } else { gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_MEDIC_CABLE_ATTACK); -// gi.WriteByte (TE_HEATBEAM); + // gi.WriteByte (TE_HEATBEAM); gi.WriteShort (self - g_edicts); gi.WritePosition (start); gi.WritePosition (tr.endpos); gi.multicast (self->s.origin, MULTICAST_PVS); -// gi.multicast (self->s.origin, MULTICAST_ALL); + // gi.multicast (self->s.origin, MULTICAST_ALL); } if ((tr.ent != self) && (tr.ent->takedamage)) @@ -969,12 +969,12 @@ Fires a gib projectile. Used by the Zombie. gi.multicast (ent->s.origin, MULTICAST_PVS); } -// no more touches +// no more touches ent->touch = NULL; ent->nextthink = level.time + 3; ent->think = G_FreeEdict; - //G_FreeEdict (ent); +// G_FreeEdict (ent); } @@ -991,7 +991,7 @@ void q1_fire_gib (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int sp VectorCopy (start, gib->s.origin); VectorScale (aimdir, speed, gib->velocity); VectorMA (gib->velocity, 200, up, gib->velocity); - //VectorMA (gib->velocity, 20, right, gib->velocity); +// VectorMA (gib->velocity, 20, right, gib->velocity); VectorSet (gib->avelocity, 3000, 1000, 2000); gib->movetype = MOVETYPE_BOUNCE; diff --git a/missionpack/km_cvar.c b/missionpack/km_cvar.c index 8081b08..c61eccb 100644 --- a/missionpack/km_cvar.c +++ b/missionpack/km_cvar.c @@ -157,6 +157,12 @@ cvar_t *sk_dm_start_rounds; cvar_t *sk_dm_start_prox; cvar_t *sk_dm_start_tesla; cvar_t *sk_dm_start_shocksphere; +/* +cvar_t *sk_dm_start_flares; +cvar_t *sk_dm_start_tbombs; +cvar_t *sk_dm_start_empnuke; +cvar_t *sk_dm_start_plasmashield; +*/ cvar_t *sk_dm_start_shotgun; cvar_t *sk_dm_start_sshotgun; @@ -178,6 +184,7 @@ cvar_t *sk_dm_start_shockwave; // maximum values cvar_t *sk_max_health; +cvar_t *sk_max_health_dm; cvar_t *sk_max_foodcube_health; cvar_t *sk_max_armor_jacket; cvar_t *sk_max_armor_combat; @@ -196,6 +203,13 @@ cvar_t *sk_max_flechettes; cvar_t *sk_max_rounds; cvar_t *sk_max_shocksphere; cvar_t *sk_max_fuel; +/* +cvar_t *sk_max_flares; +cvar_t *sk_max_tbombs; +cvar_t *sk_max_a2k; +cvar_t *sk_max_empnuke; +cvar_t *sk_max_plasmashield; +*/ // maximum settings if a player gets a bandolier cvar_t *sk_bando_bullets; // 300 @@ -206,6 +220,7 @@ cvar_t *sk_bando_magslugs; cvar_t *sk_bando_flechettes; // 250 cvar_t *sk_bando_rounds; // 150 cvar_t *sk_bando_fuel; +//cvar_t *sk_bando_flares; // 45 // maximum settings if a player gets a pack cvar_t *sk_pack_health; @@ -224,28 +239,42 @@ cvar_t *sk_pack_prox; cvar_t *sk_pack_tesla; cvar_t *sk_pack_shocksphere; cvar_t *sk_pack_fuel; +/* +cvar_t *sk_pack_flares; // 60 +cvar_t *sk_pack_tbombs; // 100 +cvar_t *sk_pack_a2k; // 1 +cvar_t *sk_pack_empnuke; // 100 +cvar_t *sk_pack_plasmashield; // 40 +*/ cvar_t *sk_pack_give_xatrix_ammo; cvar_t *sk_pack_give_rogue_ammo; +//cvar_t *sk_pack_give_zaero_ammo; // pickup values -cvar_t *sk_box_shells; //value of shells -cvar_t *sk_box_bullets; //value of bullets -cvar_t *sk_box_grenades; //value of grenade pack -cvar_t *sk_box_rockets; //value of rocket pack -cvar_t *sk_box_cells; //value of cell pack -cvar_t *sk_box_slugs; //value of slug box -cvar_t *sk_box_magslugs; //value ofmagslug box -cvar_t *sk_box_flechettes; //value of flechettes -cvar_t *sk_box_prox; //value of prox -cvar_t *sk_box_tesla; //value of tesla pack -cvar_t *sk_box_disruptors; //value of disruptor pack -cvar_t *sk_box_shocksphere; //value of shocksphere -cvar_t *sk_box_trap; //value of trap -cvar_t *sk_box_fuel; //value of fuel +cvar_t *sk_box_shells; // value of shells +cvar_t *sk_box_bullets; // value of bullets +cvar_t *sk_box_grenades; // value of grenade pack +cvar_t *sk_box_rockets; // value of rocket pack +cvar_t *sk_box_cells; // value of cell pack +cvar_t *sk_box_slugs; // value of slug box +cvar_t *sk_box_magslugs; // value ofmagslug box +cvar_t *sk_box_flechettes; // value of flechettes +cvar_t *sk_box_prox; // value of prox +cvar_t *sk_box_tesla; // value of tesla pack +cvar_t *sk_box_disruptors; // value of disruptor pack +cvar_t *sk_box_shocksphere; // value of shocksphere +cvar_t *sk_box_trap; // value of trap +cvar_t *sk_box_fuel; // value of fuel +/* +cvar_t *sk_box_flares; // value of flares box +cvar_t *sk_box_tbombs; // value of IRED box +cvar_t *sk_box_empnuke; // value of EMP nuke +cvar_t *sk_box_plasmashield; // value of plasma shield +*/ // items/powerups -cvar_t *sk_armor_bonus_value; //value of armor shards -cvar_t *sk_health_bonus_value; //value of stimpacks +cvar_t *sk_armor_bonus_value; // value of armor shards +cvar_t *sk_health_bonus_value; // value of stimpacks cvar_t *sk_powerup_max; cvar_t *sk_nuke_max; cvar_t *sk_nbomb_max; @@ -266,6 +295,11 @@ cvar_t *sk_ir_time; cvar_t *sk_double_time; cvar_t *sk_quad_fire_time; cvar_t *sk_stasis_time; +/* +cvar_t *sk_visor_time; +cvar_t *sk_sniper_charge_time; +cvar_t *sk_a2k_detonate_time; +*/ void InitLithiumVars (void) @@ -422,6 +456,12 @@ void InitLithiumVars (void) sk_dm_start_prox = gi.cvar("sk_dm_start_prox", "0", 0); sk_dm_start_tesla = gi.cvar("sk_dm_start_tesla", "0", 0); sk_dm_start_shocksphere = gi.cvar("sk_dm_start_shocksphere", "0", 0); +/* + sk_dm_start_flares = gi.cvar("sk_dm_start_flares", "0", 0); + sk_dm_start_tbombs = gi.cvar("sk_dm_start_tbombs", "0", 0); + sk_dm_start_empnuke = gi.cvar("sk_dm_start_empnuke", "0", 0); + sk_dm_start_plasmashield = gi.cvar("sk_dm_start_plasmashield", "0", 0); +*/ sk_dm_start_shotgun = gi.cvar("sk_dm_start_shotgun", "0", 0); sk_dm_start_sshotgun = gi.cvar("sk_dm_start_sshotgun", "0", 0); @@ -443,6 +483,7 @@ void InitLithiumVars (void) // maximum values sk_max_health = gi.cvar("sk_max_health", "100", 0); + sk_max_health_dm = gi.cvar("sk_max_health_dm", "120", 0); sk_max_foodcube_health = gi.cvar("sk_max_foodcube_health", "300", 0); sk_max_armor_jacket = gi.cvar("sk_max_armor_jacket", "50", 0); sk_max_armor_combat = gi.cvar("sk_max_armor_combat", "100", 0); @@ -461,6 +502,13 @@ void InitLithiumVars (void) sk_max_rounds = gi.cvar("sk_max_rounds", "100", 0); sk_max_shocksphere = gi.cvar("sk_max_shocksphere", "10", 0); sk_max_fuel = gi.cvar("sk_max_fuel", "1000", 0); +/* + sk_max_flares = gi.cvar("sk_max_flares", "30", 0); + sk_max_tbombs = gi.cvar("sk_max_tbombs", "30", 0); + sk_max_a2k = gi.cvar("sk_max_a2k", "1", 0); + sk_max_empnuke = gi.cvar("sk_max_empnuke", "50", 0); + sk_max_plasmashield = gi.cvar("sk_max_plasmashield", "20", 0); +*/ // maximum settings if a player gets a bandolier sk_bando_bullets = gi.cvar("sk_bando_bullets", "250", 0); @@ -471,6 +519,7 @@ void InitLithiumVars (void) sk_bando_flechettes = gi.cvar("sk_bando_flechettes", "250", 0); sk_bando_rounds = gi.cvar("sk_bando_rounds", "150", 0); sk_bando_fuel = gi.cvar("sk_bando_fuel", "1500", 0); +// sk_bando_flares = gi.cvar("sk_bando_flares", "50", 0); // maximum settings if a player gets a pack sk_pack_health = gi.cvar("sk_pack_health", "120", 0); @@ -489,8 +538,17 @@ void InitLithiumVars (void) sk_pack_tesla = gi.cvar("sk_pack_tesla", "100", 0); sk_pack_shocksphere = gi.cvar("sk_pack_shocksphere", "20", 0); sk_pack_fuel = gi.cvar("sk_pack_fuel", "2000", 0); +/* + sk_pack_flares = gi.cvar("sk_pack_flares", "100", 0); + sk_pack_tbombs = gi.cvar("sk_pack_tbombs", "100", 0); + sk_pack_a2k = gi.cvar("sk_pack_a2k", "1", 0); + sk_pack_empnuke = gi.cvar("sk_pack_empnuke", "100", 0); + sk_pack_plasmashield = gi.cvar("sk_pack_plasmashield", "40", 0); +*/ + sk_pack_give_xatrix_ammo = gi.cvar("sk_pack_give_xatrix_ammo", "0", CVAR_ARCHIVE); sk_pack_give_rogue_ammo = gi.cvar("sk_pack_give_rogue_ammo", "0", CVAR_ARCHIVE); +// sk_pack_give_zaero_ammo = gi.cvar("sk_pack_give_zaero_ammo", "0", CVAR_ARCHIVE); // pickup values sk_box_shells = gi.cvar("sk_box_shells", "10", 0); @@ -507,6 +565,12 @@ void InitLithiumVars (void) sk_box_shocksphere = gi.cvar("sk_box_shocksphere", "1", 0); sk_box_trap = gi.cvar("sk_box_trap", "1", 0); sk_box_fuel = gi.cvar("sk_box_fuel", "500", 0); +/* + sk_box_flares = gi.cvar("sk_box_flares", "3", 0); + sk_box_tbombs = gi.cvar("sk_box_tbombs", "3", 0); + sk_box_empnuke = gi.cvar("sk_box_empnuke", "1", 0); + sk_box_plasmashield = gi.cvar("sk_box_plasmashield", "1", 0); +*/ // items/powerups sk_armor_bonus_value = gi.cvar("sk_armor_bonus_value", "2", 0); @@ -531,4 +595,9 @@ void InitLithiumVars (void) sk_double_time = gi.cvar("sk_double_time", "30", 0); sk_quad_fire_time = gi.cvar("sk_quad_fire_time", "30", 0); sk_stasis_time = gi.cvar("sk_stasis_time", "30", 0); +/* + sk_visor_time = gi.cvar("sk_visor_time", "30", 0); + sk_sniper_charge_time = gi.cvar("sk_sniper_charge_time", "3", 0); + sk_a2k_detonate_time = gi.cvar("sk_a2k_detonate_time", "5", 0); +*/ } diff --git a/missionpack/km_cvar.h b/missionpack/km_cvar.h index 390a9b9..274df30 100644 --- a/missionpack/km_cvar.h +++ b/missionpack/km_cvar.h @@ -153,6 +153,12 @@ extern cvar_t *sk_dm_start_rounds; extern cvar_t *sk_dm_start_prox; extern cvar_t *sk_dm_start_tesla; extern cvar_t *sk_dm_start_shocksphere; +/* +extern cvar_t *sk_dm_start_flares; +extern cvar_t *sk_dm_start_tbombs; +extern cvar_t *sk_dm_start_empnuke; +extern cvar_t *sk_dm_start_plasmashield; +*/ extern cvar_t *sk_dm_start_shotgun; extern cvar_t *sk_dm_start_sshotgun; @@ -174,6 +180,7 @@ extern cvar_t *sk_dm_start_shockwave; // maximum values extern cvar_t *sk_max_health; +extern cvar_t *sk_max_health_dm; extern cvar_t *sk_max_foodcube_health; extern cvar_t *sk_max_armor; extern cvar_t *sk_max_armor_jacket; @@ -193,6 +200,13 @@ extern cvar_t *sk_max_prox; extern cvar_t *sk_max_tesla; extern cvar_t *sk_max_shocksphere; extern cvar_t *sk_max_fuel; +/* +extern cvar_t *sk_max_flares; +extern cvar_t *sk_max_tbombs; +extern cvar_t *sk_max_a2k; +extern cvar_t *sk_max_empnuke; +extern cvar_t *sk_max_plasmashield; +*/ // maximum settings if a player gets a bandolier extern cvar_t *sk_bando_bullets; @@ -203,6 +217,7 @@ extern cvar_t *sk_bando_magslugs; extern cvar_t *sk_bando_flechettes; extern cvar_t *sk_bando_rounds; extern cvar_t *sk_bando_fuel; +//extern cvar_t *sk_bando_flares; // maximum settings if a player gets a pack extern cvar_t *sk_pack_bullets; @@ -219,8 +234,17 @@ extern cvar_t *sk_pack_prox; extern cvar_t *sk_pack_tesla; extern cvar_t *sk_pack_shocksphere; extern cvar_t *sk_pack_fuel; +/* +extern cvar_t *sk_pack_flares; +extern cvar_t *sk_pack_tbombs; +extern cvar_t *sk_pack_a2k; +extern cvar_t *sk_pack_empnuke; +extern cvar_t *sk_pack_plasmashield; +*/ + extern cvar_t *sk_pack_give_xatrix_ammo; extern cvar_t *sk_pack_give_rogue_ammo; +//extern cvar_t *sk_pack_give_zaero_ammo; // pickup values extern cvar_t *sk_box_shells; //value of shells @@ -237,6 +261,12 @@ extern cvar_t *sk_box_disruptors; //value of disruptor pack extern cvar_t *sk_box_shocksphere; //value of shocksphere extern cvar_t *sk_box_trap; //value of trap extern cvar_t *sk_box_fuel; //value of fuel +/* +extern cvar_t *sk_box_flares; +extern cvar_t *sk_box_tbombs; +extern cvar_t *sk_box_empnuke; +extern cvar_t *sk_box_plasmashield; +*/ // items/powerups extern cvar_t *sk_armor_bonus_value; //value of armor shards @@ -261,3 +291,8 @@ extern cvar_t *sk_double_time; extern cvar_t *sk_quad_fire_time; extern cvar_t *sk_doppleganger_time; extern cvar_t *sk_stasis_time; +/* +extern cvar_t *sk_visor_time; +extern cvar_t *sk_sniper_charge_time; +extern cvar_t *sk_a2k_detonate_time; +*/ \ No newline at end of file diff --git a/missionpack/m_boss2.c b/missionpack/m_boss2.c index d8b996b..1ed61db 100644 --- a/missionpack/m_boss2.c +++ b/missionpack/m_boss2.c @@ -653,8 +653,8 @@ void boss2_pain (edict_t *self, edict_t *other, float kick, int damage) if (self->health < (self->max_health / 2)) { self->s.skinnum |= 1; - if (!(self->fogclip & 2)) //custom bloodtype flag check - self->blood_type = 3; //sparks and blood + if (!(self->fogclip & 2)) // custom bloodtype flag check + self->blood_type = 3; // sparks and blood } if (level.time < self->pain_debounce_time) diff --git a/missionpack/m_boss31.c b/missionpack/m_boss31.c index e7f3200..9a55365 100644 --- a/missionpack/m_boss31.c +++ b/missionpack/m_boss31.c @@ -400,8 +400,8 @@ void jorg_pain (edict_t *self, edict_t *other, float kick, int damage) if (self->health < (self->max_health / 2)) { self->s.skinnum |= 1; - if (!(self->fogclip & 2)) //custom bloodtype flag check - self->blood_type = 3; //sparks and blood + if (!(self->fogclip & 2)) // custom bloodtype flag check + self->blood_type = 3; // sparks and blood } self->s.sound = 0; diff --git a/missionpack/m_boss32.c b/missionpack/m_boss32.c index 127b9a3..4d54310 100644 --- a/missionpack/m_boss32.c +++ b/missionpack/m_boss32.c @@ -563,8 +563,8 @@ void makron_pain (edict_t *self, edict_t *other, float kick, int damage) if (self->health < (self->max_health / 2)) { self->s.skinnum |= 1; - if (!(self->fogclip & 2)) //custom bloodtype flag check - self->blood_type = 3; //sparks and blood + if (!(self->fogclip & 2)) // custom bloodtype flag check + self->blood_type = 3; // sparks and blood } if (level.time < self->pain_debounce_time) diff --git a/missionpack/m_boss5.c b/missionpack/m_boss5.c index 983ee11..449b5c1 100644 --- a/missionpack/m_boss5.c +++ b/missionpack/m_boss5.c @@ -434,8 +434,8 @@ void boss5_pain (edict_t *self, edict_t *other, float kick, int damage) if (self->health < (self->max_health / 2)) { self->s.skinnum |= 1; - if (!(self->fogclip & 2)) //custom bloodtype flag check - self->blood_type = 3; //sparks and blood + if (!(self->fogclip & 2)) // custom bloodtype flag check + self->blood_type = 3; // sparks and blood } if (level.time < self->pain_debounce_time) diff --git a/missionpack/m_carrier.c b/missionpack/m_carrier.c index 3b1b4d0..85ecf49 100644 --- a/missionpack/m_carrier.c +++ b/missionpack/m_carrier.c @@ -1112,8 +1112,8 @@ void carrier_pain (edict_t *self, edict_t *other, float kick, int damage) if (self->health < (self->max_health / 2)) { self->s.skinnum |= 1; - if (!(self->fogclip & 2)) //custom bloodtype flag check - self->blood_type = 3; //sparks and blood + if (!(self->fogclip & 2)) // custom bloodtype flag check + self->blood_type = 3; // sparks and blood } if (skill->value == 3) diff --git a/missionpack/m_chick.c b/missionpack/m_chick.c index feaef7b..09ae048 100644 --- a/missionpack/m_chick.c +++ b/missionpack/m_chick.c @@ -262,8 +262,8 @@ void chick_pain (edict_t *self, edict_t *other, float kick, int damage) //Knightmare- fixed this invalid classname check if (self->spawnflags & SF_MONSTER_SPECIAL) { - if (!(self->fogclip & 2)) //custom bloodtype flag check - self->blood_type = 0; //ordinary blood + if (!(self->fogclip & 2)) // custom bloodtype flag check + self->blood_type = 0; // ordinary blood } self->s.skinnum |= 1; } diff --git a/missionpack/m_float.c b/missionpack/m_float.c index 25ffbe1..3dca0cf 100644 --- a/missionpack/m_float.c +++ b/missionpack/m_float.c @@ -606,8 +606,8 @@ void floater_pain (edict_t *self, edict_t *other, float kick, int damage) if (self->health < (self->max_health / 2)) { self->s.skinnum |= 1; - if (!(self->fogclip & 2)) //custom bloodtype flag check - self->blood_type = 3; //sparks and blood + if (!(self->fogclip & 2)) // custom bloodtype flag check + self->blood_type = 3; // sparks and blood } if (level.time < self->pain_debounce_time) diff --git a/missionpack/m_infantry.c b/missionpack/m_infantry.c index b5058a1..1487ccf 100644 --- a/missionpack/m_infantry.c +++ b/missionpack/m_infantry.c @@ -310,7 +310,7 @@ void infantry_sight (edict_t *self, edict_t *other) gi.sound (self, CHAN_BODY, sound_sight, 1, ATTN_NORM, 0); } -//Knightmare- this was missing +// Knightmare- this was missing void infantry_search (edict_t *self) { gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0); @@ -789,6 +789,25 @@ void infantry_sidestep (edict_t *self) self->monsterinfo.currentmove = &infantry_move_run; } +// Zaero added +void SP_monster_infantry_precache (void) +{ + sound_pain1 = gi.soundindex ("infantry/infpain1.wav"); + sound_pain2 = gi.soundindex ("infantry/infpain2.wav"); + sound_die1 = gi.soundindex ("infantry/infdeth1.wav"); + sound_die2 = gi.soundindex ("infantry/infdeth2.wav"); + + sound_gunshot = gi.soundindex ("infantry/infatck1.wav"); + sound_weapon_cock = gi.soundindex ("infantry/infatck3.wav"); + sound_punch_swing = gi.soundindex ("infantry/infatck2.wav"); + sound_punch_hit = gi.soundindex ("infantry/melee2.wav"); + + sound_sight = gi.soundindex ("infantry/infsght1.wav"); + sound_search = gi.soundindex ("infantry/infsrch1.wav"); + sound_idle = gi.soundindex ("infantry/infidle1.wav"); +} +// end Zaero + /*QUAKED monster_infantry (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight GoodGuy NoGib */ void SP_monster_infantry (edict_t *self) @@ -813,7 +832,6 @@ void SP_monster_infantry (edict_t *self) sound_search = gi.soundindex ("infantry/infsrch1.wav"); sound_idle = gi.soundindex ("infantry/infidle1.wav"); - self->movetype = MOVETYPE_STEP; self->solid = SOLID_BBOX; @@ -828,11 +846,11 @@ void SP_monster_infantry (edict_t *self) VectorSet (self->mins, -16, -16, -24); VectorSet (self->maxs, 16, 16, 32); - if(!self->health) + if (!self->health) self->health = 100; - if(!self->gib_health) + if (!self->gib_health) self->gib_health = -50; - if(!self->mass) + if (!self->mass) self->mass = 200; self->pain = infantry_pain; @@ -851,12 +869,12 @@ void SP_monster_infantry (edict_t *self) self->monsterinfo.attack = infantry_attack; self->monsterinfo.melee = NULL; self->monsterinfo.sight = infantry_sight; - self->monsterinfo.search = infantry_search; //Knightmare- this was missing + self->monsterinfo.search = infantry_search; // Knightmare- this was missing self->monsterinfo.idle = infantry_fidget; self->monsterinfo.blocked = infantry_blocked; // Lazarus - if(self->powerarmor) + if (self->powerarmor) { if (self->powerarmortype == 1) self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; @@ -873,7 +891,7 @@ void SP_monster_infantry (edict_t *self) gi.linkentity (self); self->monsterinfo.currentmove = &infantry_move_stand; - if(self->health < 0) + if (self->health < 0) { mmove_t *deathmoves[] = {&infantry_move_death1, &infantry_move_death2, @@ -885,3 +903,42 @@ void SP_monster_infantry (edict_t *self) walkmonster_start (self); } + +// Zaero added +void handler_ConvertToInfantry (edict_t *self) +{ + self->s.modelindex = gi.modelindex("models/monsters/infantry/tris.md2"); + + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, 32); + + self->pain = infantry_pain; + self->die = infantry_die; + + self->s.origin[0] -= 18; + self->s.origin[1] -= 9; + + self->monsterinfo.stand = infantry_stand; + self->monsterinfo.walk = infantry_walk; + self->monsterinfo.run = infantry_run; + // pmm + self->monsterinfo.dodge = M_MonsterDodge; + self->monsterinfo.duck = infantry_duck; + self->monsterinfo.unduck = monster_duck_up; + self->monsterinfo.sidestep = infantry_sidestep; +// self->monsterinfo.dodge = infantry_dodge; + // pmm + self->monsterinfo.attack = infantry_attack; + self->monsterinfo.melee = NULL; + self->monsterinfo.sight = infantry_sight; + self->monsterinfo.search = infantry_search; // Knightmare- this was missing + self->monsterinfo.idle = infantry_fidget; + self->monsterinfo.blocked = infantry_blocked; + + self->s.frame = FRAME_run01; + +// self->common_name = "Enforcer"; + + infantry_run (self); +} +// end Zaero diff --git a/missionpack/m_medic.c b/missionpack/m_medic.c index 3900a4e..2d4f736 100644 --- a/missionpack/m_medic.c +++ b/missionpack/m_medic.c @@ -436,7 +436,7 @@ void medic_idle (edict_t *self) // AND the medic has previously called FoundTarget (trail_time set to // level.time), then look for hint_path chain and follow it, hopefully // to find monsters to resurrect - if(self->monsterinfo.aiflags & AI_HINT_TEST) + if (self->monsterinfo.aiflags2 & AI2_HINT_TEST) return; if(hint_paths_present && !(self->monsterinfo.aiflags & AI_STAND_GROUND) diff --git a/missionpack/m_supertank.c b/missionpack/m_supertank.c index 95fd853..7301f23 100644 --- a/missionpack/m_supertank.c +++ b/missionpack/m_supertank.c @@ -433,8 +433,8 @@ void supertank_pain (edict_t *self, edict_t *other, float kick, int damage) if (self->health < (self->max_health / 2)) { self->s.skinnum |= 1; - if (!(self->fogclip & 2)) //custom bloodtype flag check - self->blood_type = 3; //sparks and blood + if (!(self->fogclip & 2)) // custom bloodtype flag check + self->blood_type = 3; // sparks and blood } if (level.time < self->pain_debounce_time) diff --git a/missionpack/m_tank.c b/missionpack/m_tank.c index 0b3107a..204868c 100644 --- a/missionpack/m_tank.c +++ b/missionpack/m_tank.c @@ -269,8 +269,8 @@ void tank_pain (edict_t *self, edict_t *other, float kick, int damage) if (self->health < (self->max_health / 2)) { self->s.skinnum |= 1; - if (!(self->fogclip & 2)) //custom bloodtype flag check - self->blood_type = 3; //sparks and blood + if (!(self->fogclip & 2)) // custom bloodtype flag check + self->blood_type = 3; // sparks and blood } if (damage <= 10) return; diff --git a/missionpack/m_widow2.c b/missionpack/m_widow2.c index f28bf0d..381df29 100644 --- a/missionpack/m_widow2.c +++ b/missionpack/m_widow2.c @@ -934,8 +934,8 @@ void widow2_pain (edict_t *self, edict_t *other, float kick, int damage) if (self->health < (self->max_health / 2)) { self->s.skinnum |= 1; - if (!(self->fogclip& 2)) //custom bloodtype flag check - self->blood_type = 3; //sparks and blood + if (!(self->fogclip & 2)) // custom bloodtype flag check + self->blood_type = 3; // sparks and blood } if (skill->value == 3) diff --git a/missionpack/missionpack.dsp b/missionpack/missionpack.dsp index 4744f60..ed4ac1c 100644 --- a/missionpack/missionpack.dsp +++ b/missionpack/missionpack.dsp @@ -521,12 +521,36 @@ SOURCE=.\q_shared.c # End Source File # Begin Source File +SOURCE=.\z_ai.c +# End Source File +# Begin Source File + +SOURCE=.\z_boss.c +# End Source File +# Begin Source File + +SOURCE=.\z_handler.c +# End Source File +# Begin Source File + SOURCE=.\z_hound.c # End Source File # Begin Source File +SOURCE=.\z_item.c +# End Source File +# Begin Source File + SOURCE=.\z_sentien.c # End Source File +# Begin Source File + +SOURCE=.\z_trigger.c +# End Source File +# Begin Source File + +SOURCE=.\z_weapon.c +# End Source File # End Group # Begin Group "Header Files" @@ -753,6 +777,14 @@ SOURCE=.\z_anim.h # End Source File # Begin Source File +SOURCE=.\z_boss.h +# End Source File +# Begin Source File + +SOURCE=.\z_handler.h +# End Source File +# Begin Source File + SOURCE=.\z_hound.h # End Source File # Begin Source File diff --git a/missionpack/missionpack_2008.vcproj b/missionpack/missionpack_2008.vcproj index 01377f8..e08f358 100644 --- a/missionpack/missionpack_2008.vcproj +++ b/missionpack/missionpack_2008.vcproj @@ -842,14 +842,38 @@ RelativePath="q_shared.c" > + + + + + + + + + + + + + + + + diff --git a/missionpack/p_client.c b/missionpack/p_client.c index 5ed64ee..ed37a4c 100644 --- a/missionpack/p_client.c +++ b/missionpack/p_client.c @@ -60,6 +60,7 @@ void SP_misc_teleporter_dest (edict_t *ent); { spot = G_Spawn(); spot->classname = "info_player_coop"; + spot->spawnflags2 = 0; // Zaero added spot->s.origin[0] = 188 - 64; spot->s.origin[1] = -164; spot->s.origin[2] = 80; @@ -68,6 +69,7 @@ void SP_misc_teleporter_dest (edict_t *ent); spot = G_Spawn(); spot->classname = "info_player_coop"; + spot->spawnflags2 = 0; // Zaero added spot->s.origin[0] = 188 + 64; spot->s.origin[1] = -164; spot->s.origin[2] = 80; @@ -76,6 +78,7 @@ void SP_misc_teleporter_dest (edict_t *ent); spot = G_Spawn(); spot->classname = "info_player_coop"; + spot->spawnflags2 = 0; // Zaero added spot->s.origin[0] = 188 + 128; spot->s.origin[1] = -164; spot->s.origin[2] = 80; @@ -914,7 +917,36 @@ void ClientObituary (edict_t *self, edict_t *inflictor, edict_t *attacker) } // Hound else if (!strcmp(attacker->classname, "monster_hound")) - message = "was mauled by a"; + // message = "was mauled by a"; + message = "was leg humped to death by a"; + // Handler + else if (!strcmp(attacker->classname, "monster_handler")) + { + // message = "was ravished by an"; + if (mod == MOD_HIT) + message = "was bludgened by an"; + else + message = "was pumped full of lead by an"; + } + // ZBoss + else if (!strcmp(attacker->classname, "monster_zboss")) + { + // message = "was killed by a big, bad"; + if (mod == MOD_HIT) + message = "was pulverized by a big, bad"; + else if (mod == MOD_ROCKET) { + message = "ate a big, bad"; + message2 = "'s rocket"; + } + else if (mod == MOD_R_SPLASH) { + message = "almost dodged a big, bad"; + message2 = "'s rocket"; + } + else { + message = "was obliterated by a big, bad"; + message2 = "'s plasma cannon"; + } + } // Rottweiler else if (!strcmp(attacker->classname, "monster_dog")) message = "was mauled by a"; @@ -1578,7 +1610,10 @@ void InitClientPersistant (gclient_t *client, int style) //client->pers.weapon = item; client->pers.health = 100; - client->pers.max_health = sk_max_health->value; + if (deathmatch->value) + client->pers.max_health = sk_max_health_dm->value; + else + client->pers.max_health = sk_max_health->value; client->pers.max_fc_health = sk_max_foodcube_health->value; client->pers.max_bullets = sk_max_bullets->value; client->pers.max_shells = sk_max_shells->value; @@ -1592,12 +1627,22 @@ void InitClientPersistant (gclient_t *client, int style) client->pers.max_homing_rockets = sk_max_rockets->value; client->pers.max_fuel = sk_max_fuel->value; -//ROGUE +// ROGUE client->pers.max_prox = sk_max_prox->value; client->pers.max_tesla = sk_max_tesla->value; client->pers.max_flechettes = sk_max_flechettes->value; client->pers.max_disruptors = sk_max_rounds->value; -//ROGUE +// end ROGUE + +// Zaero + // These are currently unused, but init them anyway. + client->pers.max_flares = 30; // sk_max_flares->value; + client->pers.max_tbombs = 30; // sk_max_tbombs->value; + client->pers.max_a2k = 1; // sk_max_a2k->value; + client->pers.max_empnuke = 50; // sk_max_empnuke->value; + client->pers.max_plasmashield = 20; // sk_max_plasmashield->value; +// end Zaero + client->pers.fire_mode = 0; // Lazarus alternate fire mode client->pers.connected = true; @@ -2581,7 +2626,7 @@ void ClientBegin (edict_t *ent) return; } - Fog_Off (false); + Fog_Off (ent); stuffcmd(ent,"alias +zoomin zoomin;alias -zoomin zoominstop\n"); stuffcmd(ent,"alias +zoomout zoomout;alias -zoomout zoomoutstop\n"); diff --git a/missionpack/p_hud.c b/missionpack/p_hud.c index f111bc8..6b9b919 100644 --- a/missionpack/p_hud.c +++ b/missionpack/p_hud.c @@ -38,6 +38,7 @@ void MoveClientToIntermission (edict_t *ent) ent->client->breather_framenum = 0; ent->client->enviro_framenum = 0; ent->client->grenade_blew_up = false; + ent->client->bfg_missfire = false; // Knightmare- added for Zaero EMP Nuke ent->client->grenade_time = 0; ent->client->ps.rdflags &= ~RDF_IRGOGGLES; // PGM diff --git a/missionpack/p_view.c b/missionpack/p_view.c index ecfca00..19e7766 100644 --- a/missionpack/p_view.c +++ b/missionpack/p_view.c @@ -612,7 +612,7 @@ void SV_CalcBlend (edict_t *ent) } //PGM - if(ent->client->nuke_framenum > level.framenum) + if (ent->client->nuke_framenum > level.framenum) { float brightness; brightness = (ent->client->nuke_framenum - level.framenum) / 20.0; @@ -652,6 +652,18 @@ void SV_CalcBlend (edict_t *ent) if (ent->client->bonus_alpha > 0) SV_AddBlend (0.85, 0.7, 0.3, ent->client->bonus_alpha, ent->client->ps.blend); + // Zaero added + // for blinding + if (ent->client->flashTime > 0) + { + float alpha = (float)ent->client->flashTime / (float)ent->client->flashBase; + if (alpha > 1) + alpha = 1; + SV_AddBlend(1, 1, 1, alpha, ent->client->ps.blend); + ent->client->flashTime--; + } + // end Zaero + // drop the damage value ent->client->damage_alpha -= 0.06; if (ent->client->damage_alpha < 0) @@ -671,7 +683,7 @@ void SV_CalcBlend (edict_t *ent) if ((ent->health <= 0) && (Q_stricmp(vid_ref->string,"gl")) && (Q_stricmp(vid_ref->string,"kmgl"))) ent->client->fadein = 0; - if(ent->client->fadein > level.framenum) + if (ent->client->fadein > level.framenum) { alpha = ent->client->fadealpha*(1.0 - (ent->client->fadein-level.framenum)/(ent->client->fadein-ent->client->fadestart)); SV_AddBlend (ent->client->fadecolor[0], @@ -679,14 +691,14 @@ void SV_CalcBlend (edict_t *ent) ent->client->fadecolor[2], alpha, ent->client->ps.blend); } - else if(ent->client->fadehold > level.framenum) + else if (ent->client->fadehold > level.framenum) { SV_AddBlend (ent->client->fadecolor[0], ent->client->fadecolor[1], ent->client->fadecolor[2], ent->client->fadealpha, ent->client->ps.blend); } - else if(ent->client->fadeout > level.framenum) + else if (ent->client->fadeout > level.framenum) { alpha = ent->client->fadealpha*((ent->client->fadeout-level.framenum)/(ent->client->fadeout-ent->client->fadehold)); SV_AddBlend (ent->client->fadecolor[0], diff --git a/missionpack/p_weapon.c b/missionpack/p_weapon.c index 1054f12..9c04887 100644 --- a/missionpack/p_weapon.c +++ b/missionpack/p_weapon.c @@ -1461,12 +1461,22 @@ void Weapon_RocketLauncher_Fire (edict_t *ent, qboolean altfire) VectorSet(offset, 8, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + + // Zaero add + if (EMPNukeCheck(ent, start)) + { + ent->client->ps.gunframe++; + gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); + return; + } + // end Zaero + // KM changed constant 650 for cvar sk_rocket_speed->value - if(ent->client->pers.fire_mode) + if (ent->client->pers.fire_mode) { edict_t *target; - if(ent->client->homing_rocket && ent->client->homing_rocket->inuse) + if (ent->client->homing_rocket && ent->client->homing_rocket->inuse) { ent->client->ps.gunframe++; return; @@ -1479,9 +1489,9 @@ void Weapon_RocketLauncher_Fire (edict_t *ent, qboolean altfire) fire_rocket (ent, start, forward, damage, sk_rocket_speed->value, damage_radius, radius_damage, NULL); // send muzzle flash - //Knightmare- Gen cam code -// if(ent->client && ent->client->chasetoggle) - if(ent->client && ent->client->chaseactive) + // Knightmare- Gen cam code +// if (ent->client && ent->client->chasetoggle) + if (ent->client && ent->client->chaseactive) { gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent->client->oldplayer-g_edicts); @@ -1536,7 +1546,8 @@ BLASTER / HYPERBLASTER ====================================================================== */ -void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect, int color) +//void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect, int color) +int Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect, int color) { vec3_t forward, right; vec3_t start; @@ -1556,6 +1567,14 @@ void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, in VectorScale (forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -1; + // Zaero add + if (EMPNukeCheck(ent, start)) + { + gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); + return 0; + } + // end Zaero + if (!hyper) fire_blaster (ent, start, forward, damage, sk_blaster_speed->value, effect, hyper, color); else @@ -1614,6 +1633,7 @@ void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, in gi.multicast (ent->s.origin, MULTICAST_PVS); } PlayerNoise(ent, start, PNOISE_WEAPON); + return 1; } @@ -1723,9 +1743,11 @@ void Weapon_HyperBlaster_Fire (edict_t *ent, qboolean altfire) damage = sk_hyperblaster_damage_dm->value; else damage = sk_hyperblaster_damage->value; - Blaster_Fire (ent, offset, damage, true, effect, color); - if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) - ent->client->pers.inventory[ent->client->ammo_index]--; + // Blaster_Fire (ent, offset, damage, true, effect, color); + if ( Blaster_Fire (ent, offset, damage, true, effect, color) ) { + if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) + ent->client->pers.inventory[ent->client->ammo_index]--; + } ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) @@ -1980,7 +2002,7 @@ void Chaingun_Fire (edict_t *ent, qboolean altfire) // kick *= damage_multiplier; //PGM } - if (is_double) + if (is_double) { damage *= 2; kick *= 2; @@ -1992,6 +2014,14 @@ void Chaingun_Fire (edict_t *ent, qboolean altfire) ent->client->kick_angles[i] = crandom() * 0.7; } + // Zaero add + if (EMPNukeCheck(ent, ent->s.origin)) + { + gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); + return; + } + // end Zaero + for (i=0 ; iviewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + + // Zaero add + if (EMPNukeCheck(ent, start)) + { + ent->client->ps.gunframe++; + gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); + return; + } + // end Zaero + fire_rail (ent, start, forward, damage, kick); // send muzzle flash - //Knightmare- Gen cam code -// if(ent->client && ent->client->chasetoggle) - if(ent->client && ent->client->chaseactive) + // Knightmare- Gen cam code +// if (ent->client && ent->client->chasetoggle) + if (ent->client && ent->client->chaseactive) { gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent->client->oldplayer-g_edicts); @@ -2312,6 +2352,34 @@ void weapon_bfg_fire (edict_t *ent, qboolean altfire) int damage; float damage_radius = sk_bfg_radius->value; + // Zaero- moved AngleVectors/VectorSet/P_ProjectSource here + AngleVectors (ent->client->v_angle, forward, right, NULL); + VectorSet (offset, 8, 8, ent->viewheight-8); + P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + + // Zaero add + if (ent->client->ps.gunframe == 9) + { + // ent->flags &= ~FL_BFGMISSFIRE; + ent->client->bfg_missfire = false; + } + +// if ( !(ent->flags & FL_BFGMISSFIRE) && EMPNukeCheck(ent, start)) + if ( !ent->client->bfg_missfire && EMPNukeCheck(ent, start) ) + { + // ent->flags |= FL_BFGMISSFIRE; + ent->client->bfg_missfire = true; + gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); + } + +// if (ent->flags & FL_BFGMISSFIRE) + if (ent->client->bfg_missfire) + { + ent->client->ps.gunframe++; + return; + } + // end Zaero + if (deathmatch->value) damage = sk_bfg_damage_dm->value; else @@ -2320,9 +2388,9 @@ void weapon_bfg_fire (edict_t *ent, qboolean altfire) if (ent->client->ps.gunframe == 9) { // send muzzle flash - //Knightmare- Gen cam code -// if(ent->client && ent->client->chasetoggle) - if(ent->client && ent->client->chaseactive) + // Knightmare- Gen cam code +// if (ent->client && ent->client->chasetoggle) + if (ent->client && ent->client->chaseactive) { gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent->client->oldplayer-g_edicts); @@ -2361,8 +2429,8 @@ void weapon_bfg_fire (edict_t *ent, qboolean altfire) damage *= 2; } - AngleVectors (ent->client->v_angle, forward, right, NULL); - +// Zaero- moved above +// AngleVectors (ent->client->v_angle, forward, right, NULL); VectorScale (forward, -2, ent->client->kick_origin); // make a big pitch kick with an inverse fall @@ -2370,8 +2438,10 @@ void weapon_bfg_fire (edict_t *ent, qboolean altfire) ent->client->v_dmg_roll = crandom()*8; ent->client->v_dmg_time = level.time + DAMAGE_TIME; - VectorSet(offset, 8, 8, ent->viewheight-8); +/* VectorSet(offset, 8, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); +*/ + fire_bfg (ent, start, forward, damage, sk_bfg_speed->value, damage_radius); //was 400 ent->client->ps.gunframe++; @@ -2446,6 +2516,15 @@ void weapon_ionripper_fire (edict_t *ent, qboolean altfire) P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + // Zaero add + if (EMPNukeCheck(ent, start)) + { + ent->client->ps.gunframe++; + gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); + return; + } + // end Zaero + fire_ionripper (ent, start, forward, damage, sk_ionripper_speed->value, EF_IONRIPPER); // send muzzle flash @@ -2527,6 +2606,15 @@ void weapon_phalanx_fire (edict_t *ent, qboolean altfire) VectorSet(offset, 0, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + // Zaero add + if (EMPNukeCheck(ent, start)) + { + ent->client->ps.gunframe++; + gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); + return; + } + // end Zaero + if (ent->client->ps.gunframe == 8) { v[PITCH] = ent->client->v_angle[PITCH]; @@ -2548,9 +2636,9 @@ void weapon_phalanx_fire (edict_t *ent, qboolean altfire) fire_plasma (ent, start, forward, damage, sk_phalanx_speed->value, damage_radius, radius_damage); // send muzzle flash - //Knightmare- Gen cam code -// if(ent->client && ent->client->chasetoggle) - if(ent->client && ent->client->chaseactive) + // Knightmare- Gen cam code +// if (ent->client && ent->client->chasetoggle) + if (ent->client && ent->client->chaseactive) { gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent->client->oldplayer-g_edicts); @@ -2636,7 +2724,7 @@ void Weapon_Trap (edict_t *ent) ChangeWeapon (ent); return; } - //Knightmare- no throwing traps while controlling turret + // Knightmare- no throwing traps while controlling turret if (ent->flags & FL_TURRET_OWNER) { ent->client->ps.gunframe = 0; @@ -2773,7 +2861,7 @@ void weapon_chainfist_fire (edict_t *ent, qboolean altfire) damage = sk_chainfist_damage->value; if (is_quad) -// damage *= damage_multiplier; + // damage *= damage_multiplier; damage *= 4; if (is_double) damage *= 2; @@ -2852,23 +2940,23 @@ void Weapon_ChainFist (edict_t *ent) { if((ent->client->pers.hand != CENTER_HANDED) && random() < 0.4) chainfist_smoke(ent); -// ent->client->ps.gunframe = 40; + // ent->client->ps.gunframe = 40; } else if(ent->client->ps.gunframe == 51 && (rand()&7)) { if((ent->client->pers.hand != CENTER_HANDED) && random() < 0.4) chainfist_smoke(ent); -// ent->client->ps.gunframe = 49; + // ent->client->ps.gunframe = 49; } // set the appropriate weapon sound. if(ent->client->weaponstate == WEAPON_FIRING) -// ent->client->weapon_sound = attack_index; + // ent->client->weapon_sound = attack_index; ent->client->weapon_sound = gi.soundindex("weapons/sawhit.wav"); else if(ent->client->weaponstate == WEAPON_DROPPING) ent->client->weapon_sound = 0; else -// ent->client->weapon_sound = idle_index; + // ent->client->weapon_sound = idle_index; ent->client->weapon_sound = gi.soundindex("weapons/sawidle.wav"); Weapon_Generic (ent, 4, 32, 57, 60, pause_frames, fire_frames, weapon_chainfist_fire); @@ -2942,23 +3030,32 @@ void weapon_tracker_fire (edict_t *self, qboolean altfire) VectorSet(offset, 24, 8, self->viewheight-8); P_ProjectSource (self->client, self->s.origin, offset, forward, right, start); + // Zaero add + if (EMPNukeCheck(self, start)) + { + self->client->ps.gunframe++; + gi.sound (self, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); + return; + } + // end Zaero + // FIXME - can we shorten this? do we need to? VectorMA (start, WORLD_SIZE, forward, end); // was 8192 enemy = NULL; //PMM - doing two traces .. one point and one box. tr = gi.trace (start, vec3_origin, vec3_origin, end, self, MASK_SHOT); - if(tr.ent != world) + if (tr.ent != world) { //Knightmare- track all destroyable objects - if(tr.ent->svflags & SVF_MONSTER || tr.ent->client || tr.ent->svflags & SVF_DAMAGEABLE || tr.ent->takedamage == DAMAGE_YES) + if (tr.ent->svflags & SVF_MONSTER || tr.ent->client || tr.ent->svflags & SVF_DAMAGEABLE || tr.ent->takedamage == DAMAGE_YES) { - if(tr.ent->health > 0) + if (tr.ent->health > 0) enemy = tr.ent; } } else { tr = gi.trace (start, mins, maxs, end, self, MASK_SHOT); - if(tr.ent != world) + if (tr.ent != world) { if(tr.ent->svflags & SVF_MONSTER || tr.ent->client || tr.ent->svflags & SVF_DAMAGEABLE) { @@ -2974,9 +3071,9 @@ void weapon_tracker_fire (edict_t *self, qboolean altfire) fire_tracker (self, start, forward, damage, sk_disruptor_speed->value, enemy); // send muzzle flash - //Knightmare- Gen cam code -// if(self->client && self->client->chasetoggle) - if(self->client && self->client->chaseactive) + // Knightmare- Gen cam code +// if (self->client && self->client->chasetoggle) + if (self->client && self->client->chaseactive) { gi.WriteByte (svc_muzzleflash); gi.WriteShort (self->client->oldplayer-g_edicts); @@ -3031,13 +3128,13 @@ void weapon_etf_rifle_fire (edict_t *ent, qboolean altfire) damage_radius = sk_etf_rifle_radius->value; radius_damage = sk_etf_rifle_radius_damage->value; - if(deathmatch->value) + if (deathmatch->value) damage = sk_etf_rifle_damage->value; else damage = sk_etf_rifle_damage->value; // PGM - adjusted to use the quantity entry in the weapon structure. - if(ent->client->pers.inventory[ent->client->ammo_index] < ent->client->pers.weapon->quantity) + if (ent->client->pers.inventory[ent->client->ammo_index] < ent->client->pers.weapon->quantity) { VectorClear (ent->client->kick_origin); VectorClear (ent->client->kick_angles); @@ -3063,7 +3160,7 @@ void weapon_etf_rifle_fire (edict_t *ent, qboolean altfire) damage_radius *= 2; } - for(i=0;i<3;i++) + for (i=0;i<3;i++) { ent->client->kick_origin[i] = crandom() * 0.85; ent->client->kick_angles[i] = crandom() * 0.85; @@ -3077,7 +3174,7 @@ void weapon_etf_rifle_fire (edict_t *ent, qboolean altfire) // FIXME - set correct frames for different offsets. - if(ent->client->ps.gunframe == 6) // right barrel + if (ent->client->ps.gunframe == 6) // right barrel { // gi.dprintf("right\n"); VectorSet(offset, 15, 8, -8); @@ -3096,7 +3193,7 @@ void weapon_etf_rifle_fire (edict_t *ent, qboolean altfire) // send muzzle flash //Knightmare- Gen cam code - if(ent->client && ent->client->chaseactive) + if (ent->client && ent->client->chaseactive) { gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent->client->oldplayer-g_edicts); @@ -3192,7 +3289,9 @@ void Heatbeam_Fire (edict_t *ent, qboolean altfire) // } ent->client->ps.gunframe++; - if(ent->client && !ent->client->chaseactive) //Knightmare- fix for third person mode + + // Zaero- moved below + if (ent->client && !ent->client->chaseactive) // Knightmare- fix for third person mode ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_beamer2/tris.md2"); if (is_quad) @@ -3207,20 +3306,27 @@ void Heatbeam_Fire (edict_t *ent, qboolean altfire) // get start / end positions AngleVectors (ent->client->v_angle, forward, right, up); -// This offset is the "view" offset for the beam start (used by trace) - + // This offset is the "view" offset for the beam start (used by trace) VectorSet(offset, 7, 2, ent->viewheight-3); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); // This offset is the entity offset VectorSet(offset, 2, 7, -3); + // Zaero add + if (EMPNukeCheck(ent, start)) + { + gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); + return; + } + // end Zaero + fire_heat (ent, start, forward, offset, damage, kick, false); // send muzzle flash - //Knightmare- Gen cam code -// if(ent->client && ent->client->chasetoggle) - if(ent->client && ent->client->chaseactive) + // Knightmare- Gen cam code +// if (ent->client && ent->client->chasetoggle) + if (ent->client && ent->client->chaseactive) { gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent->client->oldplayer-g_edicts); @@ -3290,7 +3396,7 @@ void Weapon_Heatbeam (edict_t *ent) // ent->client->ps.gunframe = 8; // ent->client->ps.gunskin = 0; // ent->client->ps.gunindex = on_model; - if(ent->client && !ent->client->chaseactive) //Knightmare- fix for third person mode + if (ent->client && !ent->client->chaseactive) //Knightmare- fix for third person mode ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_beamer2/tris.md2"); } else @@ -3315,7 +3421,7 @@ void Weapon_Heatbeam (edict_t *ent) { // ent->client->ps.gunskin = 1; // ent->client->ps.gunindex = off_model; - if(ent->client && !ent->client->chaseactive) //Knightmare- fix for third person mode + if (ent->client && !ent->client->chaseactive) //Knightmare- fix for third person mode ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_beamer/tris.md2"); ent->client->weapon_sound = 0; } @@ -3337,11 +3443,12 @@ SHOCKWAVE void Shockwave_Fire (edict_t *ent, qboolean altfire) { - vec3_t offset, start; - vec3_t forward, right; - int damage; - float damage_radius; - int radius_damage; + vec3_t offset, start; + vec3_t forward, right; + int damage; + float damage_radius; + int radius_damage; + qboolean emp_missfire = false; // added for Zaero damage = sk_shockwave_damage->value + (int)(random() * sk_shockwave_damage2->value); radius_damage = sk_shockwave_rdamage->value; @@ -3358,9 +3465,29 @@ void Shockwave_Fire (edict_t *ent, qboolean altfire) radius_damage *= 2; } - if (ent->client->ps.gunframe == 5) //spin up and fire sound + // Zaero- moved here + AngleVectors (ent->client->v_angle, forward, right, NULL); + VectorScale (forward, -2, ent->client->kick_origin); + ent->client->kick_angles[0] = -1; + VectorSet(offset, 0, 7, ent->viewheight-8); + P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + + // Zaero add + if (EMPNukeCheck(ent, start)) { - gi.sound (ent, CHAN_AUTO, gi.soundindex("weapons/shockfire.wav"), 1.0, ATTN_NORM, 0); + emp_missfire = true; + // ent->client->ps.gunframe++; + // gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); + // return; + } + // end Zaero + + if (ent->client->ps.gunframe == 5) // spin up and fire sound + { + if (emp_missfire) + gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); + else + gi.sound (ent, CHAN_AUTO, gi.soundindex("weapons/shockfire.wav"), 1.0, ATTN_NORM, 0); ent->client->ps.gunframe++; return; } @@ -3375,16 +3502,27 @@ void Shockwave_Fire (edict_t *ent, qboolean altfire) return; } + // Zaero add + if (emp_missfire) + { + ent->client->ps.gunframe++; + return; + } + // end Zaero + +/* Zaero- moved above AngleVectors (ent->client->v_angle, forward, right, NULL); VectorScale (forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -1; VectorSet(offset, 0, 7, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); +*/ + fire_shock_sphere (ent, start, forward, damage, sk_shockwave_speed->value, damage_radius, radius_damage); // send muzzle flash and sound - //Knightmare- Gen cam code - if(ent->client && ent->client->chaseactive) + // Knightmare- Gen cam code + if (ent->client && ent->client->chaseactive) { gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent->client->oldplayer-g_edicts); @@ -3418,7 +3556,7 @@ void Weapon_Shockwave (edict_t *ent) } //====================================================================== -void Weapon_Null(edict_t *ent) +void Weapon_Null (edict_t *ent) { if (ent->client->newweapon) ChangeWeapon(ent); @@ -3435,7 +3573,7 @@ void kick_attack (edict_t * ent ) trace_t tr; vec3_t end; - if(ent->client->quad_framenum > level.framenum) + if (ent->client->quad_framenum > level.framenum) { damage *= 4; kick *= 4; diff --git a/missionpack/q_shared.h b/missionpack/q_shared.h index ae7c003..e41f8a8 100644 --- a/missionpack/q_shared.h +++ b/missionpack/q_shared.h @@ -1316,7 +1316,7 @@ typedef enum EV_WADE, // wading or treading water EV_WADE_MUD, // wading in mud EV_CLIMB_LADDER, //climbing ladder - EV_PLAYER_TELEPORT_Q1 // Q1 teleport, sounds in rogue pak0.pak + EV_PLAYER_TELEPORT2 // Q1-style teleport, sounds in rogue pak0.pak // end Knightmare } entity_event_t; diff --git a/missionpack/z_ai.c b/missionpack/z_ai.c new file mode 100644 index 0000000..a740538 --- /dev/null +++ b/missionpack/z_ai.c @@ -0,0 +1,489 @@ +#include "g_local.h" + + +#define Z_RADUISLISTSIZE 2000 + + +void ai_run_melee(edict_t *self); +qboolean FindTarget (edict_t *self); +qboolean SV_StepDirection (edict_t *ent, float yaw, float dist); +void SV_NewChaseDir (edict_t *actor, vec3_t eOrigin, float dist); +#if 0 +void z_aiMoveTo(edict_t *self, float dist) +{ + // sanity check + if (!(self->monsterinfo.scriptState & MSS_AIMOVETO)) + return; +#if 0 + if (!SV_StepDirection (self, self->ideal_yaw, dist)) + { + SV_NewChaseDir (self, self->monsterinfo.aiMoveTo, dist); + } +#endif +} +#endif + + +/* +============= +zSchoolAllVisiable + +Creates a list of all entities in the raduis of Z_RADUISLISTSIZE +============== +*/ +void zCreateRaduisList (edict_t *self) +{ + edict_t *head, *list; + vec3_t vec; + + if(self->zRaduisList) + { // already created for this think, don't bother doing it again... + return; + } + + head = NULL; + list = self; + + while(1) + { + head = findradius(head, self->s.origin, Z_RADUISLISTSIZE); + if(head == NULL) + break; + + if(head != self) + { + list->zRaduisList = head; + VectorSubtract(self->s.origin, head->s.origin, vec); + head->zDistance = VectorLength(vec); + list = head; + } + } + + list->zRaduisList = NULL; +}; + + + +/* +============= +zSchoolAllVisiable + +Create list of monsters of the same schooling type that are ahead of you. +============== +*/ +int zSchoolAllVisiable (edict_t *self) +{ + int max; + edict_t *head, *list; + + max = 0; + + zCreateRaduisList(self); + head = self->zRaduisList; + list = self; + + while (head) + { + if (strcmp(head->classname, self->classname) == 0 + && (self->monsterinfo.aiflags2 & AI2_SCHOOLING) && (head->health > 0) + && (head->zDistance <= self->monsterinfo.zSchoolSightRadius) + && (visible(self, head)) && (infront(self, head)) ) + { + list->zSchoolChain = head; + list = head; + max++; + } + head = head->zRaduisList; + } + + list->zSchoolChain = NULL; + + return max; +} + + + + +/* +============= +zFindRoamYaw + +Check direction moving in does not hit a wall... if it does change direction. +============== +*/ +int zFindRoamYaw (edict_t *self, float distcheck) +{ + vec3_t forward, end, angles; + trace_t tr; + float current = anglemod(self->s.angles[YAW]); + + if (current <= self->ideal_yaw - 1 || current > self->ideal_yaw + 1) + { + if(fabs(current - self->ideal_yaw) <= 359.0) + { + return 0; + } + } + + AngleVectors (self->s.angles, forward, NULL, NULL); + VectorMA (self->s.origin, distcheck, forward, end); + + tr = gi.trace (self->s.origin, self->mins, self->maxs, end, self, MASK_SOLID); + + if (tr.fraction < 1.0) + { + if (random() > 0.75) + { + self->ideal_yaw = vectoyaw(forward); + self->ideal_yaw = self->ideal_yaw + 180; + } + else + { + float dir = random() > 0.5 ? -45 : 45; + float maxtrys = 100; + + VectorCopy(self->s.angles, angles); + + while (tr.fraction < 1.0 && maxtrys) + { + // blocked, change ideal yaw... + self->ideal_yaw = vectoyaw(forward); + self->ideal_yaw = self->ideal_yaw + (random() * dir); + // self->ideal_yaw = self->ideal_yaw + (-45 + (random() * 90)); + + angles[YAW] = anglemod (self->ideal_yaw); + AngleVectors (angles, forward, NULL, NULL); + VectorMA (self->s.origin, distcheck, forward, end); + + tr = gi.trace (self->s.origin, self->mins, self->maxs, end, self, MASK_SOLID); + maxtrys--; + } + } + + return 1; + } + + return 0; +}; + + + +/* +============= +zSchoolMonsters + +Roaming schooling ai. +============== +*/ +int zSchoolMonsters (edict_t *self, float dist, int runStyle, float *currentSpeed) +{ + int maxInsight; + int newRunStyle; + + maxInsight = zSchoolAllVisiable(self); + + // If you're not out in front + if (maxInsight > 0) + { + float totalSpeed; + float totalBearing; + float distanceToNearest, distanceToLeader, dist; + edict_t *nearestEntity, *list; + vec3_t vec; + + totalSpeed = 0; + totalBearing = 0; + distanceToNearest = 10000; + distanceToLeader = 0; + list = self->zSchoolChain; + + while (list) + { + // Gather data on those you see + totalSpeed += list->speed; + totalBearing += anglemod(list->s.angles[YAW]); + + VectorSubtract(self->s.origin, list->s.origin, vec); + dist = VectorLength(vec); + + if (dist < distanceToNearest) + { + distanceToNearest = dist; + nearestEntity = list; + } + + if (dist > distanceToLeader) + { + distanceToLeader = dist; + } + + list = list->zSchoolChain; + } + + // Rule 1) Match average speed of those in the list + self->speed = (totalSpeed / maxInsight) * 1.5; + + // Rule 2) Move towards the perceived center of gravity of the herd + self->ideal_yaw = totalBearing / maxInsight; + + // check if hitting something + if (!zFindRoamYaw(self, 10)) + { + // Rule 3) Maintain a minimum distance from those around you + if (distanceToNearest <= self->monsterinfo.zSchoolMinimumDistance) + { + self->ideal_yaw = nearestEntity->s.angles[YAW]; + self->speed = nearestEntity->speed; + } + } + + } + else + { //You are in front, so slow down a bit + edict_t *head; + + self->speed = (self->speed * self->monsterinfo.zSchoolDecayRate); + + // check direction + zFindRoamYaw(self, 100); + + // change directions of the monsters following you... + zCreateRaduisList(self); + head = self->zRaduisList; + + while (head) + { + if (strcmp(head->classname, self->classname) == 0 && (head->health > 0) && + (head->zDistance <= self->monsterinfo.zSchoolSightRadius) && (visible(self, head))) + + { + head->ideal_yaw = self->ideal_yaw + (-20 + (random() * 40)); + } + head = head->zRaduisList; + } + } + + // if(self.rm_schoolFlags & 1) + // { // check to see is I keep away from "other" entities... + // zSchoolCheckForOtherEntities(checkOtherRaduis); + // } + + if (self->speed > self->monsterinfo.zSchoolMaxSpeed) + { + self->speed = self->monsterinfo.zSchoolMaxSpeed; + } + + if (self->speed < self->monsterinfo.zSchoolMinSpeed) + { + self->speed = self->monsterinfo.zSchoolMinSpeed; + } + + if (self->speed <= self->monsterinfo.zSpeedStandMax) + { + newRunStyle = 0; + + if(newRunStyle != runStyle) + { + *currentSpeed = 1; + } + else + { + *currentSpeed = (self->speed - self->monsterinfo.zSchoolMinSpeed) + 1; + } + } + else if (self->speed <= self->monsterinfo.zSpeedWalkMax) + { + newRunStyle = 1; + + if (newRunStyle != runStyle) + { + *currentSpeed = 1; + } + else + { + *currentSpeed = (self->speed - self->monsterinfo.zSpeedStandMax) + 1; + } + } + else + { + newRunStyle = 2; + + if(newRunStyle != runStyle) + { + *currentSpeed = 1; + } + else + { + *currentSpeed = (self->speed - self->monsterinfo.zSpeedWalkMax) + 1; + } + } + + return newRunStyle; +} + + + +/* +============= +ai_schoolStand + +Used for standing around and looking for players / schooling monsters of the same type. +Distance is for slight position adjustments needed by the animations +============== +*/ +void ai_schoolStand (edict_t *self, float dist) +{ + float speed; + + if (!(self->monsterinfo.aiflags2 & AI2_SCHOOLING)) + { + ai_stand(self, dist); + return; + } + + // init school var's for this frame + self->zRaduisList = NULL; + + if (self->enemy || FindTarget(self)) + { + ai_stand(self, dist); + return; + } + else + { + // run schooling routines + switch (zSchoolMonsters(self, dist, 0, &speed)) + { + case 1: + self->monsterinfo.walk (self); + break; + case 2: + self->monsterinfo.run (self); + break; + } + } + + // do the normal stand stuff + if (dist) + M_walkmove (self, self->ideal_yaw, dist); + // M_walkmove (self, self->ideal_yaw, dist * speed); +} + + + + + +/* +============= +ai_schoolRun + +The monster has an enemy it is trying to kill +============= +*/ +void ai_schoolRun (edict_t *self, float dist) +{ + float speed; + + if (!(self->monsterinfo.aiflags2 & AI2_SCHOOLING)) + { + ai_run(self, dist); + return; + } + + // init school var's for this frame + self->zRaduisList = NULL; + + if (self->enemy || FindTarget(self)) + { + ai_run(self, dist); + return; + } + else + { + // run schooling routines + switch (zSchoolMonsters(self, dist, 2, &speed)) + { + case 0: + self->monsterinfo.stand (self); + break; + case 1: + self->monsterinfo.walk (self); + break; + } + } + + // do the normal run stuff + SV_StepDirection (self, self->ideal_yaw, dist); +// SV_StepDirection (self, self->ideal_yaw, dist * speed); +} + + + +/* +============= +ai_schoolWalk + +The monster is walking it's beat +============= +*/ +void ai_schoolWalk (edict_t *self, float dist) +{ + float speed; + + if (!(self->monsterinfo.aiflags2 & AI2_SCHOOLING)) + { + ai_walk(self, dist); + return; + } + + // init school var's for this frame + self->zRaduisList = NULL; + + if (self->enemy || FindTarget(self)) + { + ai_walk(self, dist); + return; + } + else + { + // run schooling routines + switch (zSchoolMonsters(self, dist, 1, &speed)) + { + case 0: + self->monsterinfo.stand (self); + break; + case 2: + self->monsterinfo.run (self); + break; + } + } + + // do the normal walk stuff + SV_StepDirection (self, self->ideal_yaw, dist); +// SV_StepDirection (self, self->ideal_yaw, dist * speed); +} + + + +/* +============= +ai_schoolCharge + +Turns towards target and advances +Use this call with a distnace of 0 to replace ai_face +============== +*/ +void ai_schoolCharge (edict_t *self, float dist) +{ + /* + if(!(self->monsterinfo.aiflags & AI_SCHOOLING)) + { + ai_charge(self, dist); + return; + } + */ + ai_charge(self, dist); +} + + + diff --git a/missionpack/z_boss.c b/missionpack/z_boss.c new file mode 100644 index 0000000..160a55c --- /dev/null +++ b/missionpack/z_boss.c @@ -0,0 +1,1853 @@ +#include "g_local.h" +#include "z_anim.h" + +#include "z_boss.h" + +static int sound_pain1; +static int sound_pain2; +static int sound_pain3; +static int sound_die1; +static int sound_die2; +static int sound_hookimpact; +static int sound_sight; +static int sound_hooklaunch; +static int sound_hookfly; +static int sound_swing; +static int sound_idle1; +static int sound_idle2; +static int sound_walk; +static int sound_raisegun; +static int sound_lowergun; +static int sound_switchattacks; +static int sound_plamsaballfly; +static int sound_plamsaballexplode; +static int sound_plamsaballfire; +static int sound_taunt1; +static int sound_taunt2; +static int sound_taunt3; + + +void fire_empnuke(edict_t *ent, vec3_t center, int radius); +void SV_AddGravity (edict_t *ent); + +void zboss_stand (edict_t *self); +void zboss_run (edict_t *self); +void zboss_run2 (edict_t *self); +void zboss_walk (edict_t *self); +void zboss_walk2(edict_t *self); +void zboss_chooseNextAttack(edict_t *self); +void zboss_reelInGraaple(edict_t *self); +void zboss_posthook(edict_t *self); +void HookDragThink (edict_t *self); +void zboss_attack (edict_t *self); + + +void zboss_walksound (edict_t *self) +{ + gi.sound (self, CHAN_BODY, sound_walk, 1, ATTN_NORM, 0); +} + + +void zboss_sight (edict_t *self, edict_t *other) +{ + gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0); +} + + +void possibleBossTaunt (edict_t *self) +{ + float r = random(); + + if (random() < 0.10) + { + if (r < 0.33) + { + gi.sound (self, CHAN_VOICE, sound_taunt1, 1, ATTN_NORM, 0); + } + else if (r < 0.66) + { + gi.sound (self, CHAN_VOICE, sound_taunt2, 1, ATTN_NORM, 0); + } + else + { + gi.sound (self, CHAN_VOICE, sound_taunt3, 1, ATTN_NORM, 0); + } + } +} + + +// +// STAND +// +mframe_t zboss_frames_stand1 [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 9 + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 19 + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 29 + + ai_stand, 0, NULL, + ai_stand, 0, NULL, +}; +mmove_t zboss_stand1 = {FRAME_stand1start, FRAME_stand1end, zboss_frames_stand1, zboss_stand}; + + +mframe_t zboss_frames_stand2 [] = +{ + ai_stand, 0, NULL, // 32 + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 41 + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, // 51 + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL // 56 +}; +mmove_t zboss_stand2 = {FRAME_stand2start, FRAME_stand2end, zboss_frames_stand2, zboss_stand}; + + +void zboss_standidle (edict_t *self) +{ + if (random() < 0.8) + { + gi.sound (self, CHAN_VOICE, sound_idle1, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &zboss_stand1; + } + else + { + gi.sound (self, CHAN_VOICE, sound_idle2, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &zboss_stand2; + } +} + + +// +// Post WALK/RUN leading into ilde. +// +mframe_t zboss_frames_postwalk [] = +{ + ai_walk, 3, NULL, // 177 + ai_walk, 3, NULL, + ai_walk, 3, NULL, + ai_walk, 3, NULL, + ai_walk, 3, NULL, + ai_walk, 3, NULL, + ai_walk, 3, NULL, + ai_walk, 3, NULL, // 184 +}; +mmove_t zboss_move_postwalk = {FRAME_postWalkStart, FRAME_postWalkEnd, zboss_frames_postwalk, zboss_standidle}; + + +void zboss_postWalkRun (edict_t *self) +{ + self->monsterinfo.currentmove = &zboss_move_postwalk; +} + + +// +// WALK +// +mframe_t zboss_frames_prewalk [] = +{ + ai_walk, 3, NULL, //154 + ai_walk, 3, NULL, + ai_walk, 3, NULL, + ai_walk, 3, NULL, + ai_walk, 3, NULL, + ai_walk, 3, NULL, + ai_walk, 3, NULL, // 160 +}; +mmove_t zboss_move_prewalk = {FRAME_preWalkStart, FRAME_preWalkEnd, zboss_frames_prewalk, zboss_walk2}; + + +mframe_t zboss_frames_walk [] = +{ + ai_walk, 2, NULL, //161 + ai_walk, 3, NULL, + ai_walk, 3, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 3, zboss_walksound, + ai_walk, 4, NULL, + ai_walk, 4, NULL, // 170 + ai_walk, 4, NULL, + ai_walk, 4, NULL, + ai_walk, 3, NULL, + ai_walk, 2, NULL, + ai_walk, 2, NULL, + ai_walk, 3, zboss_walksound, // 176 +}; +mmove_t zboss_move_walk = {FRAME_walkStart, FRAME_walkEnd, zboss_frames_walk, zboss_walk2}; + + +void zboss_walk (edict_t *self) +{ + self->monsterinfo.currentmove = &zboss_move_prewalk; +} + +void zboss_walk2 (edict_t *self) +{ + self->monsterinfo.currentmove = &zboss_move_walk; +} + + +// +// RUN +// +mframe_t zboss_frames_prerun [] = +{ + ai_run, 3, NULL, //154 + ai_run, 3, NULL, + ai_run, 3, NULL, + ai_run, 3, NULL, + ai_run, 3, NULL, + ai_run, 3, NULL, + ai_run, 3, NULL, // 160 +}; +mmove_t zboss_move_prerun = {FRAME_preWalkStart, FRAME_preWalkEnd, zboss_frames_prerun, zboss_run2}; + + +mframe_t zboss_frames_run [] = +{ + ai_run, 2, NULL, //161 + ai_run, 3, NULL, + ai_run, 3, NULL, + ai_run, 4, NULL, + ai_run, 4, NULL, + ai_run, 4, NULL, + ai_run, 4, NULL, + ai_run, 3, zboss_walksound, + ai_run, 4, NULL, + ai_run, 4, NULL, // 170 + ai_run, 4, NULL, + ai_run, 4, NULL, + ai_run, 3, NULL, + ai_run, 2, NULL, + ai_run, 2, NULL, + ai_run, 3, zboss_walksound, // 176 +}; +mmove_t zboss_move_run = {FRAME_walkStart, FRAME_walkEnd, zboss_frames_run, NULL}; + + +void zboss_run (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + zboss_stand(self); + else + self->monsterinfo.currentmove = &zboss_move_prerun; +} + + +void zboss_run2 (edict_t *self) +{ + if (self->monsterinfo.aiflags & AI_STAND_GROUND) + zboss_stand(self); + else + self->monsterinfo.currentmove = &zboss_move_run; +} + + +// +// main stand function +// +void zboss_stand (edict_t *self) +{ + if (self->monsterinfo.currentmove == &zboss_move_prewalk || + self->monsterinfo.currentmove == &zboss_move_walk || + self->monsterinfo.currentmove == &zboss_move_prerun || + self->monsterinfo.currentmove == &zboss_move_run) + { + zboss_postWalkRun(self); + } + else + { + zboss_standidle(self); + } +} + + +// +// PAIN +// +mframe_t zboss_frames_pain1 [] = +{ + ai_move, 0, NULL, // 185 + ai_move, 0, NULL, + ai_move, 0, NULL // 187 +}; +mmove_t zboss_move_pain1 = {FRAME_pain1Start, FRAME_pain1End, zboss_frames_pain1, zboss_run}; + + +mframe_t zboss_frames_pain2 [] = +{ + ai_move, 0, NULL, // 188 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL // 192 +}; +mmove_t zboss_move_pain2 = {FRAME_pain2Start, FRAME_pain2End, zboss_frames_pain2, zboss_run}; + + +mframe_t zboss_frames_pain3 [] = +{ + ai_move, 0, NULL, // 193 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 202 + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 212 + + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL // 217 +}; +mmove_t zboss_move_pain3 = {FRAME_pain3Start, FRAME_pain3End, zboss_frames_pain3, zboss_run}; + + +void zboss_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + float r; + float hbreak = (self->max_health / 3.0); + + // set the skin + if (self->health < hbreak) + { + self->s.skinnum = (self->style * 3) + 2; + } + else if (self->health < hbreak * 2) + { + self->s.skinnum = (self->style * 3) + 1; + } + else + { + self->s.skinnum = (self->style * 3) + 0; + } + + r = random(); + if (r < 0.125) + { + gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); + } + else if (r < 0.25) + { + gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); + } + else if (r < 0.375) + { + gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM, 0); + } + else if (r < 0.5) + { + gi.sound (self, CHAN_VOICE, sound_taunt1, 1, ATTN_NORM, 0); + } + else if (r < 0.625) + { + gi.sound (self, CHAN_VOICE, sound_taunt2, 1, ATTN_NORM, 0); + } + else if (r < 0.75) + { + gi.sound (self, CHAN_VOICE, sound_taunt3, 1, ATTN_NORM, 0); + } + + if (self->bossFireCount && self->bossFireTimeout < level.time) + { + self->bossFireCount = 0; + } + + if (self->bossFireCount > 40 && self->bossFireTimeout > level.time) + { + // that's it, we are pissed... + if (self->zDistance < level.time) + { + fire_empnuke(self, self->s.origin, 1024); + self->zDistance = level.time + 30 + (random() * 5); + } + zboss_attack(self); + self->bossFireCount = 0; + self->bossFireTimeout = 0; + return; + } + + self->bossFireCount++; + self->bossFireTimeout = level.time + 1; + + + if (self->health < (self->max_health / 4) && self->zDistance < level.time) + { + fire_empnuke(self, self->s.origin, 1024); + self->zDistance = level.time + 30 + (random() * 5); + } + + if (level.time < self->pain_debounce_time) + return; + + self->pain_debounce_time = level.time + 5; + + if (skill->value == 3) + return; // no pain anims in nightmare + + if (self->laser) + return; // while hook is out. + + r = random(); + + if (damage > 150 && r < 0.33) + { + self->monsterinfo.currentmove = &zboss_move_pain3; + } + else if (damage > 80 && r < 0.66) + { + self->monsterinfo.currentmove = &zboss_move_pain2; + } + else if (r < 0.60) + { + self->monsterinfo.currentmove = &zboss_move_pain1; + } +} + + +// +// MELEE +// +void zboss_swing (edict_t *self) +{ + static vec3_t aim = {MELEE_DISTANCE, 0, -24}; + fire_hit (self, aim, (15 + (rand() % 6)), 800); +} + + +mframe_t zboss_frames_attack2c [] = +{ + ai_charge, 0, NULL, // 110 + ai_charge, 0, zboss_swing, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, possibleBossTaunt, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, zboss_swing, + ai_charge, 0, NULL // 118 +}; +mmove_t zboss_move_attack2c = {FRAME_attack2cStart, FRAME_attack2cEnd, zboss_frames_attack2c, zboss_posthook}; + + +void zboss_melee2 (edict_t *self) +{ + self->monsterinfo.currentmove = &zboss_move_attack2c; + gi.sound (self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0); +} + + +mframe_t zboss_frames_premelee [] = +{ + ai_charge, 0, NULL, // 57 + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, possibleBossTaunt, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, // 66 +}; +mmove_t zboss_move_premelee = {FRAME_preHookStart, FRAME_preHookEnd, zboss_frames_premelee, zboss_melee2 }; + +// todo, pickup player, and throw... + + +void zboss_melee (edict_t *self) +{ + gi.sound (self, CHAN_BODY, sound_raisegun, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &zboss_move_premelee; +} + +// +// ATTACK +// + +// Rocket / Hook + +// Rocket attack + +mframe_t zboss_frames_attack1b [] = +{ + ai_charge, 0, NULL, // 92 + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL // 98 +}; +mmove_t zboss_move_attack1b = {FRAME_attack1bStart, FRAME_attack1bEnd, zboss_frames_attack1b, zboss_chooseNextAttack }; + + +void zboss_reloadRockets(edict_t *self) +{ + self->monsterinfo.aiflags2 &= ~AI2_ONESHOTTARGET; + self->monsterinfo.currentmove = &zboss_move_attack1b; +} + + +static vec3_t rocketoffset[] = +{ + {-5, -50, 33}, + {-5, -39, 27}, + {-5, -39, 39}, + {-5, -44, 27}, + {-5, -44, 39}, + {-5, -48, 29}, + {-5, -48, 29}, +}; + + +void FireFlare (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t dir; + vec3_t vec; + + int offset = (self->s.frame - 71) / 3; + + AngleVectors (self->s.angles, forward, right, NULL); + + G_ProjectSource (self->s.origin, rocketoffset[offset], forward, right, start); + + if (self->monsterinfo.aiflags2 & AI2_ONESHOTTARGET) + { + VectorCopy( self->monsterinfo.shottarget, vec ); + } + else + { + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + } + + VectorSubtract (vec, start, dir); + VectorNormalize (dir); + + if (!(self->monsterinfo.aiflags2 & AI2_ONESHOTTARGET)) + { + ANIM_AIM(self, dir); + } + fire_flare (self, start, dir, 10, 1000, 10, 10); + + // play shooting sound + gi.sound(self, CHAN_WEAPON, gi.soundindex("weapons/flare/shoot.wav"), 1, ATTN_NORM, 0); +} + + +void FireRocket (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t dir; + vec3_t vec; + + int offset = (self->s.frame - 71) / 3; + + AngleVectors (self->s.angles, forward, right, NULL); + + G_ProjectSource (self->s.origin, rocketoffset[offset], forward, right, start); + + if (self->monsterinfo.aiflags2 & AI2_ONESHOTTARGET) + { + VectorCopy( self->monsterinfo.shottarget, vec ); + } + else + { + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + } + + vec[0] += (100 - (200 * random())); + vec[1] += (100 - (200 * random())); + vec[2] += (40 - (80 * random())); + VectorSubtract (vec, start, dir); + VectorNormalize (dir); + + +// ANIM_AIM(self, dir); + fire_rocket (self, start, dir, 70, 500, 70+20, 70, NULL); + + gi.WriteByte (svc_muzzleflash2); + gi.WriteShort (self - g_edicts); + gi.WriteByte (MZ2_BOSS2_ROCKET_1); + gi.multicast (start, MULTICAST_PVS); +} + + +mframe_t zboss_frames_attack1a [] = +{ + ai_charge, 0, FireFlare, // 71 + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, FireRocket, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, FireRocket, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, FireRocket, + ai_charge, 0, possibleBossTaunt, + ai_charge, 0, NULL, + ai_charge, 0, FireFlare, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, FireRocket, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, FireRocket, + ai_charge, 0, NULL, + ai_charge, 0, NULL, // 91 +}; +mmove_t zboss_move_attack1a = {FRAME_attack1aStart, FRAME_attack1aEnd, zboss_frames_attack1a, zboss_reloadRockets }; + + +// hook + +void zboss_reelInGraaple2 (edict_t *self) +{ + vec3_t vec, dir; + float length; + edict_t *enemy = self->laser->enemy; + vec3_t hookoffset = {-5, -24, 34}; + vec3_t forward, right; + + AngleVectors (self->s.angles, forward, right, NULL); + G_ProjectSource(self->s.origin, hookoffset, forward, right, vec); + VectorSubtract (vec, self->laser->s.origin, dir); + length = VectorLength (dir); + + if (length <= 80 || (self->laser->think == HookDragThink && self->laser->powerarmor_time < level.time)) + { + G_FreeEdict(self->laser); + self->laser = NULL; + + self->s.modelindex3 = gi.modelindex ("models/monsters/bossz/grapple/tris.md2"); + + if (enemy) + { + VectorClear(enemy->velocity); + zboss_melee2(self); + } + else + { + zboss_chooseNextAttack(self); + } + } + else + { + zboss_reelInGraaple(self); + } +} + + +mframe_t zboss_frames_attack2b [] = +{ + ai_charge, 0, NULL, // 107 + ai_charge, 0, NULL, + ai_charge, 0, NULL // 109 +}; +mmove_t zboss_move_attack2b = {FRAME_attack2bStart, FRAME_attack2bEnd, zboss_frames_attack2b, zboss_reelInGraaple2 }; + + +void HookDragThink (edict_t *self) +{ + vec3_t dir, vec; + float length, speed; + vec3_t hookoffset = {-5, -24, 34}; + vec3_t forward, right; + vec3_t offset = {0, 0, 0}; + + if (self->enemy && self->enemy->health > 0) + { + VectorCopy (self->enemy->s.origin, self->s.origin); + } + + VectorSubtract (self->owner->s.origin, self->s.origin, dir); + length = VectorLength (dir); + + AngleVectors (self->owner->s.angles, forward, right, NULL); + G_ProjectSource(self->owner->s.origin, hookoffset, forward, right, vec); + + VectorSubtract (vec, self->s.origin, dir); + speed = VectorLength (dir); + VectorNormalize (dir); +/* + if(speed > 1000) + { + speed = 1000; + } + else if(speed < 500) + { + speed = (speed * 2) + 100; + } +*/ + speed = 1000; + VectorScale (dir, speed, self->velocity); + + if (self->enemy && self->enemy->health > 0) + { + VectorCopy (self->velocity, self->enemy->velocity); + self->enemy->velocity[2] *= 1.3; + } + + gi.WriteByte (svc_temp_entity); +#if 0 //def USE_GRAPPLE_CABLE + gi.WriteByte (TE_GRAPPLE_CABLE); + gi.WriteShort (self - g_edicts); + gi.WritePosition (self->s.origin); + gi.WritePosition (vec); + gi.WritePosition (offset); +#else + gi.WriteByte (TE_MEDIC_CABLE_ATTACK); + gi.WriteShort (self - g_edicts); + gi.WritePosition (self->s.origin); + gi.WritePosition (vec); +#endif + gi.multicast (self->s.origin, MULTICAST_PVS); + + self->nextthink = level.time + FRAMETIME; +} + + +void HookTouch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + if (other == ent->owner) + return; + + if (other->takedamage) + { + gi.sound (ent, CHAN_WEAPON, sound_hookimpact, 1, ATTN_NORM, 0); + // T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, 10, 0, 0, MOD_ROCKET); + T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, 10, 0, 0, MOD_HIT); + } + + if (other->client && other->health > 0) + { // alive... Let's drag the bastard back... + ent->enemy = other; + } + + ent->powerarmor_time = level.time + 15; + VectorClear(ent->velocity); + ent->nextthink = level.time + FRAMETIME; + ent->think = HookDragThink; + ent->s.frame = 283; +} + + +void HookThink (edict_t *self) +{ + vec3_t vec; + vec3_t hookoffset = {-3, -24, 34}; + vec3_t forward, right; + vec3_t offset = {0, 0, 0}; + + if (self->powerarmor_time < level.time) + { + self->powerarmor_time = level.time + 15; + VectorClear(self->velocity); + self->enemy = NULL; + self->think = HookDragThink; + self->s.frame = 283; + } + + + AngleVectors (self->owner->s.angles, forward, right, NULL); + G_ProjectSource(self->owner->s.origin, hookoffset, forward, right, vec); + + gi.WriteByte (svc_temp_entity); +#if 0 //def USE_GRAPPLE_CABLE + gi.WriteByte (TE_GRAPPLE_CABLE); + gi.WriteShort (self - g_edicts); + gi.WritePosition (self->s.origin); + gi.WritePosition (vec); + gi.WritePosition (offset); +#else + gi.WriteByte (TE_MEDIC_CABLE_ATTACK); + gi.WriteShort (self - g_edicts); + gi.WritePosition (self->s.origin); + gi.WritePosition (vec); +#endif + gi.multicast (self->s.origin, MULTICAST_PVS); + + self->nextthink = level.time + FRAMETIME; +} + + +void FireHook (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t dir; + vec3_t vec; + vec3_t hookoffset = {-1, -24, 34}; + edict_t *hook; + float speed; + + AngleVectors (self->s.angles, forward, right, NULL); + + G_ProjectSource (self->s.origin, hookoffset, forward, right, start); + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + VectorSubtract (vec, start, dir); + VectorNormalize (dir); + + ANIM_AIM(self, dir); + + self->s.modelindex3 = 0; + + speed = 1000; + + gi.sound (self, CHAN_WEAPON, sound_hooklaunch, 1, ATTN_NORM, 0); + + self->laser = hook = G_Spawn(); + VectorCopy (start, hook->s.origin); + VectorCopy (dir, hook->movedir); + vectoangles (dir, hook->s.angles); + VectorScale (dir, speed, hook->velocity); + hook->movetype = MOVETYPE_FLYMISSILE; + hook->clipmask = MASK_SHOT; + hook->solid = SOLID_BBOX; + VectorClear (hook->mins); + VectorClear (hook->maxs); + hook->s.modelindex = gi.modelindex ("models/monsters/bossz/grapple/tris.md2"); + hook->s.frame = 282; + hook->owner = self; + hook->touch = HookTouch; + hook->powerarmor_time = level.time + 8000 / speed; + hook->nextthink = level.time + FRAMETIME; + hook->think = HookThink; + hook->s.sound = sound_hookfly; // replace... + hook->classname = "bosshook"; + + gi.linkentity (hook); +} + + +void zboss_reelInGraaple (edict_t *self) +{ + self->monsterinfo.currentmove = &zboss_move_attack2b; +} + + +mframe_t zboss_frames_attack2a [] = +{ + ai_charge, 0, NULL, // 99 + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, possibleBossTaunt, + ai_charge, 0, NULL, + ai_charge, 0, FireHook, // 104 + ai_charge, 0, NULL, + ai_charge, 0, NULL, // 106 +}; +mmove_t zboss_move_attack2a = {FRAME_attack2aStart, FRAME_attack2aEnd, zboss_frames_attack2a, zboss_reelInGraaple }; + + +mframe_t zboss_frames_posthook [] = +{ + ai_charge, 0, NULL, // 136 + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, // 141 +}; +mmove_t zboss_move_posthook = {FRAME_postHookStart, FRAME_postHookEnd, zboss_frames_posthook, zboss_run }; + + +void zboss_posthook (edict_t *self) +{ + self->monsterinfo.currentmove = &zboss_move_posthook; +} + + +void zboss_chooseHookRocket (edict_t *self) +{ + if (random() < 0.2 && !(self->monsterinfo.aiflags2 & AI2_ONESHOTTARGET)) + { + self->monsterinfo.currentmove = &zboss_move_attack2a; + } + else + { + self->monsterinfo.currentmove = &zboss_move_attack1a; + } +} + + +mframe_t zboss_frames_prehook [] = +{ + ai_charge, 0, NULL, // 57 + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, // 66 +}; +mmove_t zboss_move_prehook = {FRAME_preHookStart, FRAME_preHookEnd, zboss_frames_prehook, zboss_chooseHookRocket }; + + +// Plasma Cannon + +void PlasmaballBlastAnim (edict_t *ent) +{ + ent->s.frame++; + ent->s.skinnum++; + + if (ent->s.frame > 1) + { + G_FreeEdict(ent); + return; + } + else + { + ent->nextthink = level.time + FRAMETIME; + } +} + + +void Plasmaball_Explode (edict_t *ent) +{ + // FIXME: if we are onground then raise our Z just a bit since we are a point? + if (ent->enemy) + { + float points; + vec3_t v; + vec3_t dir; + + VectorAdd (ent->enemy->mins, ent->enemy->maxs, v); + VectorMA (ent->enemy->s.origin, 0.5, v, v); + VectorSubtract (ent->s.origin, v, v); + points = ent->dmg - 0.5 * VectorLength (v); + VectorSubtract (ent->enemy->s.origin, ent->s.origin, dir); + T_Damage (ent->enemy, ent, ent->owner, dir, ent->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, MOD_UNKNOWN); + } + + T_RadiusDamage(ent, ent->owner, ent->dmg, ent->enemy, ent->dmg_radius, MOD_UNKNOWN); + + VectorMA (ent->s.origin, -0.02, ent->velocity, ent->s.origin); + VectorClear(ent->velocity); + + ent->movetype = MOVETYPE_NONE; + ent->s.modelindex = gi.modelindex("models/objects/b_explode/tris.md2"); + ent->s.effects &= ~EF_BFG & ~EF_ANIM_ALLFAST; + ent->s.frame = 0; + ent->s.skinnum = 6; +// ent->s.renderfx = RF_TRANSLUCENT | RF_FULLBRIGHT; +// ent->s.renderfx = RF_TRANSLUCENT; + + gi.sound (ent, CHAN_AUTO, sound_plamsaballexplode, 1, ATTN_NORM, 0); + + ent->think = PlasmaballBlastAnim; + ent->nextthink = level.time + FRAMETIME; +} + + +/*static*/ void Plasmaball_Touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + if (other == ent->owner) + return; + + if (surf && (surf->flags & SURF_SKY)) + { + G_FreeEdict (ent); + return; + } + + ent->enemy = other; + Plasmaball_Explode (ent); +} + + +void fire_plasmaCannon (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius, float distance) +{ + edict_t *plasmaball; + vec3_t dir; + vec3_t forward, right, up; + + vectoangles (aimdir, dir); + AngleVectors (dir, forward, right, up); + + plasmaball = G_Spawn(); + VectorCopy (start, plasmaball->s.origin); + VectorScale (aimdir, speed, plasmaball->velocity); + VectorMA (plasmaball->velocity, (distance - 500) + crandom() * 10.0, up, plasmaball->velocity); + VectorMA (plasmaball->velocity, crandom() * 10.0, right, plasmaball->velocity); + VectorSet (plasmaball->avelocity, 300, 300, 300); + plasmaball->movetype = MOVETYPE_BOUNCE; + plasmaball->clipmask = MASK_SHOT; + plasmaball->solid = SOLID_BBOX; + VectorClear (plasmaball->mins); + VectorClear (plasmaball->maxs); + plasmaball->s.modelindex = gi.modelindex ("sprites/plasma1.sp2"); + plasmaball->s.effects = EF_BFG | EF_ANIM_ALLFAST; + plasmaball->owner = self; + plasmaball->touch = Plasmaball_Touch; + plasmaball->nextthink = level.time + timer; + plasmaball->think = Plasmaball_Explode; + plasmaball->dmg = damage; + plasmaball->dmg_radius = damage_radius; + plasmaball->classname = "plasmaball"; + plasmaball->s.sound = sound_plamsaballfly; + + gi.sound (self, CHAN_AUTO, sound_plamsaballfire, 1, ATTN_NORM, 0); + gi.linkentity (plasmaball); +} + + +static vec3_t cannonoffset[] = +{ + {-19, -44, 30}, + {-14, -33, 32}, + {-4 , -45, 32}, + {-2 , -34, 32}, + { 7, -49, 32}, + { 6, -36, 34}, + { 6, -36, 34}, +}; + + +void FireCannon (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t dir; + vec3_t vec; + float distance; + + int offset = (self->s.frame - 119) / 2; + + AngleVectors (self->s.angles, forward, right, NULL); + + G_ProjectSource (self->s.origin, cannonoffset[offset], forward, right, start); + + if (self->monsterinfo.aiflags2 & AI2_ONESHOTTARGET) + { + VectorCopy( self->monsterinfo.shottarget, vec ); + } + else + { + VectorCopy (self->enemy->s.origin, vec); + vec[2] += self->enemy->viewheight; + } + + if (self->timeout) + { + if (self->seq) + { + VectorNegate(right, right); + } + VectorMA (vec, self->timeout, right, vec); + } + self->timeout -= 50; + + VectorSubtract (vec, start, dir); + VectorNormalize (dir); + + VectorSubtract (self->enemy->s.origin, self->s.origin, vec); + distance = VectorLength (vec); + + if (distance < 700) + { + distance = 700; + } + +// ANIM_AIM(self, dir); + if (skill->value < 2) + { + fire_plasmaCannon (self, start, dir, 90, 700, 2.5, 90+40, distance); + } + else if (skill->value < 3) + { + fire_plasmaCannon (self, start, dir, 90, (int)(distance * 1.2), 2.5, 90+40, distance); + } + else + { + fire_plasmaCannon (self, start, dir, 90, (int)(distance * 1.6), 2.5, 90+40, distance); + } +} + + +mframe_t zboss_frames_attack3 [] = +{ + ai_charge, 0, FireCannon, // 119 + ai_charge, 0, NULL, + ai_charge, 0, FireCannon, // 121 + ai_charge, 0, NULL, + ai_charge, 0, FireCannon, // 123 + ai_charge, 0, NULL, + ai_charge, 0, FireCannon, // 125 + ai_charge, 0, possibleBossTaunt, + ai_charge, 0, FireCannon, // 127 + ai_charge, 0, NULL, + ai_charge, 0, FireCannon, // 129 + ai_charge, 0, NULL, + ai_charge, 0, FireCannon, // 131 + ai_charge, 0, NULL, // 132 +}; +mmove_t zboss_move_attack3 = {FRAME_attack3Start, FRAME_attack3End, zboss_frames_attack3, zboss_chooseNextAttack }; + + +void zboss_fireCannons (edict_t *self) +{ + self->monsterinfo.currentmove = &zboss_move_attack3; + +// self->seq = (random() > 0.5); + self->seq = 0; + self->timeout = 150; +} + + +mframe_t zboss_frames_precannon [] = +{ + ai_charge, 0, NULL, // 67 + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, // 70 +}; +mmove_t zboss_move_precannon = {FRAME_preCannonStart, FRAME_preCannonEnd, zboss_frames_precannon, zboss_fireCannons }; + + +mframe_t zboss_frames_postcannon [] = +{ + ai_charge, 0, NULL, // 133 + ai_charge, 0, NULL, + ai_charge, 0, NULL, // 135 +}; +mmove_t zboss_move_postcannon = {FRAME_postCannonStart, FRAME_postCannonEnd, zboss_frames_postcannon, zboss_run }; + + +void zboss_postcannon (edict_t *self) +{ + self->monsterinfo.currentmove = &zboss_move_postcannon; +} + + +// switching in mid attack... + +mframe_t zboss_frames_h2c [] = +{ + ai_charge, 0, NULL, // 142 + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, // 147 +}; +mmove_t zboss_move_h2c = {FRAME_attackH2CStart, FRAME_attackH2CEnd, zboss_frames_h2c, zboss_fireCannons }; + + +mframe_t zboss_frames_c2h [] = +{ + ai_charge, 0, NULL, // 148 + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, possibleBossTaunt, + ai_charge, 0, NULL, + ai_charge, 0, NULL, // 153 +}; +mmove_t zboss_move_c2h = {FRAME_attackC2HStart, FRAME_attackC2HEnd, zboss_frames_c2h, zboss_chooseHookRocket }; + + +void zboss_chooseNextAttack (edict_t *self) +{ + if (self->enemy == NULL) + return; + + self->monsterinfo.aiflags2 &= ~AI2_ONESHOTTARGET; + + if (random() < 0.5 && self->enemy) + { + if (random() < 0.4) + { + if (self->monsterinfo.currentmove == &zboss_move_attack3) + { + gi.sound (self, CHAN_BODY, sound_switchattacks, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &zboss_move_c2h; + } + else + { + zboss_chooseHookRocket(self); + } + } + else + { + if (self->monsterinfo.currentmove == &zboss_move_attack3) + { + zboss_fireCannons(self); + } + else + { + gi.sound (self, CHAN_BODY, sound_switchattacks, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &zboss_move_h2c; + } + } + } + else + { + gi.sound (self, CHAN_BODY, sound_lowergun, 1, ATTN_NORM, 0); + + if (self->monsterinfo.currentmove == &zboss_move_attack3) + { + zboss_postcannon(self); + } + else + { + zboss_posthook(self); + } + } +} + + +void zboss_attack (edict_t *self) +{ + if (self->enemy == NULL) + return; + + gi.sound (self, CHAN_BODY, sound_raisegun, 1, ATTN_NORM, 0); + + if (random() < 0.4) + { + self->monsterinfo.currentmove = &zboss_move_prehook; + } + else + { + self->monsterinfo.currentmove = &zboss_move_precannon; + } +} + + +/* +=== +Death Stuff Starts +=== +*/ + +void zboss_dead (edict_t *self) +{ + VectorSet (self->mins, -32, -74, -30); + VectorSet (self->maxs, 32, 40, 12); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); +} + + +mframe_t zboss_frames_death1 [] = +{ + ai_move, 0, NULL, // 218 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 227 + + ai_move, 0, NULL, // 228 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 236 +}; +mmove_t zboss_move_death1 = {FRAME_die1Start, FRAME_die1End, zboss_frames_death1, zboss_dead}; + + + +void FireDeadRocket1 (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t rocketoffset = {-26, -26, 25}; + + AngleVectors (self->s.angles, forward, right, NULL); + + G_ProjectSource (self->s.origin, rocketoffset, forward, right, start); + + fire_rocket (self, start, forward, 70, 500, 70+20, 70, NULL); + + gi.WriteByte (svc_muzzleflash2); + gi.WriteShort (self - g_edicts); + gi.WriteByte (MZ2_BOSS2_ROCKET_1); + gi.multicast (start, MULTICAST_PVS); +} + + +void FireDeadRocket2 (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t rocketoffset = {-16, -21, 20}; + + AngleVectors (self->s.angles, forward, right, NULL); + + G_ProjectSource (self->s.origin, rocketoffset, forward, right, start); + + forward[1] += 10; + fire_rocket (self, start, forward, 70, 500, 70+20, 70, NULL); + + gi.WriteByte (svc_muzzleflash2); + gi.WriteShort (self - g_edicts); + gi.WriteByte (MZ2_BOSS2_ROCKET_1); + gi.multicast (start, MULTICAST_PVS); +} + + +void FireDeadRocket3 (edict_t *self) +{ + vec3_t forward, right, up; + vec3_t start; + vec3_t rocketoffset = {-17, -20, 30}; + + AngleVectors (self->s.angles, forward, right, up); + + G_ProjectSource (self->s.origin, rocketoffset, forward, right, start); + + fire_rocket (self, start, up, 70, 500, 70+20, 70, NULL); + + gi.WriteByte (svc_muzzleflash2); + gi.WriteShort (self - g_edicts); + gi.WriteByte (MZ2_BOSS2_ROCKET_1); + gi.multicast (start, MULTICAST_PVS); +} + + + +void FireDeadRocket4 (edict_t *self) +{ + vec3_t forward, right, up; + vec3_t start; + vec3_t rocketoffset = {-8, -16, 17}; + + AngleVectors (self->s.angles, forward, right, up); + + G_ProjectSource (self->s.origin, rocketoffset, forward, right, start); + + fire_rocket (self, start, up, 70, 500, 70+20, 70, NULL); + + gi.WriteByte (svc_muzzleflash2); + gi.WriteShort (self - g_edicts); + gi.WriteByte (MZ2_BOSS2_ROCKET_1); + gi.multicast (start, MULTICAST_PVS); +} + + +void FireDeadRocket5 (edict_t *self) +{ + vec3_t forward, right, up; + vec3_t start; + vec3_t rocketoffset = {-10, -16, 30}; + + AngleVectors (self->s.angles, forward, right, up); + + G_ProjectSource (self->s.origin, rocketoffset, forward, right, start); + VectorNegate(forward, forward); + + fire_rocket (self, start, forward, 70, 500, 70+20, 70, NULL); + + gi.WriteByte (svc_muzzleflash2); + gi.WriteShort (self - g_edicts); + gi.WriteByte (MZ2_BOSS2_ROCKET_1); + gi.multicast (start, MULTICAST_PVS); +} + +void FireDeadRocket6 (edict_t *self) +{ + vec3_t forward, right, up; + vec3_t start; + vec3_t rocketoffset = {0, -18, 25}; + + AngleVectors (self->s.angles, forward, right, up); + + G_ProjectSource (self->s.origin, rocketoffset, forward, right, start); + VectorNegate(forward, forward); + forward[1] -= 10; + + fire_rocket (self, start, forward, 70, 500, 70+20, 70, NULL); + + gi.WriteByte (svc_muzzleflash2); + gi.WriteShort (self - g_edicts); + gi.WriteByte (MZ2_BOSS2_ROCKET_1); + gi.multicast (start, MULTICAST_PVS); +} + + +void FireDeadRocket7 (edict_t *self) +{ + vec3_t forward, right, up; + vec3_t start; + vec3_t rocketoffset = {17, -27, 30}; + + AngleVectors (self->s.angles, forward, right, up); + + G_ProjectSource (self->s.origin, rocketoffset, forward, right, start); + VectorNegate(forward, forward); + forward[1] -= 10; + + fire_rocket (self, start, forward, 70, 500, 70+20, 70, NULL); + + gi.WriteByte (svc_muzzleflash2); + gi.WriteShort (self - g_edicts); + gi.WriteByte (MZ2_BOSS2_ROCKET_1); + gi.multicast (start, MULTICAST_PVS); +} + +void FireDeadCannon1 (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t cannonoffset = {9, -46, 33}; + + AngleVectors (self->s.angles, forward, right, NULL); + + G_ProjectSource (self->s.origin, cannonoffset, forward, right, start); + + fire_plasmaCannon (self, start, forward, 90, 700, 2.5, 90+40, 700); + + gi.WriteByte (svc_muzzleflash2); + gi.WriteShort (self - g_edicts); + gi.WriteByte (MZ2_GUNNER_GRENADE_1); + gi.multicast (start, MULTICAST_PVS); +} + + +void FireDeadCannon2 (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t cannonoffset = {3, -31, 37}; + + AngleVectors (self->s.angles, forward, right, NULL); + + G_ProjectSource (self->s.origin, cannonoffset, forward, right, start); + + fire_plasmaCannon (self, start, forward, 90, 700, 2.5, 90+40, 700); + + gi.WriteByte (svc_muzzleflash2); + gi.WriteShort (self - g_edicts); + gi.WriteByte (MZ2_GUNNER_GRENADE_1); + gi.multicast (start, MULTICAST_PVS); +} + + +void FireDeadCannon3 (edict_t *self) +{ + vec3_t forward, right; + vec3_t start; + vec3_t cannonoffset = {-21, -19, 24}; + + AngleVectors (self->s.angles, forward, right, NULL); + + G_ProjectSource (self->s.origin, cannonoffset, forward, right, start); + + fire_plasmaCannon (self, start, forward, 90, 700, 2.5, 90+40, 700); + + gi.WriteByte (svc_muzzleflash2); + gi.WriteShort (self - g_edicts); + gi.WriteByte (MZ2_GUNNER_GRENADE_1); + gi.multicast (start, MULTICAST_PVS); +} + + +void DeadHookTouch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + if (other == ent->owner) + return; + + if (other->takedamage) + { + gi.sound (ent, CHAN_WEAPON, sound_hookimpact, 1, ATTN_NORM, 0); + // T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, 10, 0, 0, MOD_ROCKET); + T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, 10, 0, 0, MOD_HIT); + } + + G_FreeEdict(ent); +} + + +void FireDeadGrapple (edict_t *self) +{ + vec3_t forward, right, up; + vec3_t start; + vec3_t hookoffset = {-35, 8, 28}; + edict_t *hook; + float speed; + + if (self->s.modelindex3 == 0) // hook already out... + return; + + AngleVectors (self->s.angles, forward, right, up); + + G_ProjectSource (self->s.origin, hookoffset, forward, right, start); + + self->s.modelindex3 = 0; + + speed = 500; + + gi.sound (self, CHAN_WEAPON, sound_hooklaunch, 1, ATTN_NORM, 0); + + hook = G_Spawn(); + VectorCopy (start, hook->s.origin); + VectorCopy (up, hook->movedir); + vectoangles (up, hook->s.angles); + VectorScale (up, speed, hook->velocity); + hook->movetype = MOVETYPE_FLYMISSILE; + hook->clipmask = MASK_SHOT; + hook->solid = SOLID_BBOX; + VectorClear (hook->mins); + VectorClear (hook->maxs); + hook->s.modelindex = gi.modelindex ("models/monsters/bossz/grapple/tris.md2"); + hook->s.frame = 282; + hook->owner = self; + hook->touch = DeadHookTouch; + hook->nextthink = level.time + 8000 / speed; + hook->think = G_FreeEdict; + hook->s.sound = sound_hookfly; // replace... + hook->classname = "bosshook"; + + gi.linkentity (hook); +} + + +mframe_t zboss_frames_death2 [] = +{ + ai_move, 0, NULL, // 237 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 246 + + ai_move, 0, NULL, // 247 + ai_move, 0, NULL, + ai_move, 0, FireDeadRocket1, // 249 + ai_move, 0, FireDeadRocket2, // 250 + ai_move, 0, FireDeadRocket3, // 251 + ai_move, 0, FireDeadRocket4, // 252 + ai_move, 0, FireDeadRocket5, // 253 + ai_move, 0, FireDeadRocket6, // 254 + ai_move, 0, FireDeadRocket7, // 255 + ai_move, 0, NULL, // 256 + + ai_move, 0, FireDeadCannon1, // 257 + ai_move, 0, FireDeadCannon2, // 258 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, FireDeadCannon3, // 264 + ai_move, 0, NULL, + ai_move, 0, NULL, // 266 + + ai_move, 0, NULL, // 267 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, // 276 + + ai_move, 0, NULL, // 277 + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, NULL, + ai_move, 0, FireDeadGrapple, // 281 +}; +mmove_t zboss_move_death2 = {FRAME_die2Start, FRAME_die2End, zboss_frames_death2, zboss_dead}; + + +void zboss_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + int n; + + self->s.skinnum = (self->style * 3) + 2; + + if (self->laser) + { + G_FreeEdict(self->laser); + self->laser = NULL; + } + +// check for gib + if (self->health <= self->gib_health) + { + self->s.modelindex2 = 0; + self->s.modelindex3 = 0; + + gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0); + for (n= 0; n < 2; n++) + ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 4; n++) + ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC); + for (n= 0; n < 16; n++) + ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC); + for (n= 0; n < 16; n++) + ThrowGib (self, "models/objects/gibs/gear/tris.md2", damage, GIB_METALLIC); + ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC); + self->deadflag = DEAD_DEAD; + return; + } + + if (self->deadflag == DEAD_DEAD) + return; + +// regular death + self->deadflag = DEAD_DEAD; + self->takedamage = DAMAGE_YES; + + // todo + if (random() < 0.5) + { + gi.sound (self, CHAN_VOICE, sound_die1, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &zboss_move_death1; + } + else + { + gi.sound (self, CHAN_VOICE, sound_die2, 1, ATTN_NORM, 0); + self->monsterinfo.currentmove = &zboss_move_death2; + } +} + + +/* +=== +End Death Stuff +=== +*/ + +void SP_monster_zboss_precache (void) +{ + sound_pain1 = gi.soundindex ("monsters/bossz/bpain1.wav"); + sound_pain2 = gi.soundindex ("monsters/bossz/bpain2.wav"); + sound_pain3 = gi.soundindex ("monsters/bossz/bpain3.wav"); + sound_die1 = gi.soundindex ("monsters/bossz/bdeth1.wav"); + sound_die2 = gi.soundindex ("monsters/bossz/bdeth2.wav"); + sound_hooklaunch = gi.soundindex("monsters/bossz/bhlaunch.wav"); + sound_hookimpact = gi.soundindex("monsters/bossz/bhimpact.wav"); + sound_hookfly = gi.soundindex("monsters/bossz/bhfly.wav"); + sound_sight = gi.soundindex("monsters/bossz/bsight1.wav"); + sound_swing = gi.soundindex("monsters/bossz/bswing.wav"); + sound_idle1 = gi.soundindex("monsters/bossz/bidle1.wav"); + sound_idle2 = gi.soundindex("monsters/bossz/bidle2.wav"); + sound_walk = gi.soundindex("monsters/bossz/bwalk.wav"); + sound_raisegun = gi.soundindex("monsters/bossz/braisegun.wav"); + sound_lowergun = gi.soundindex("monsters/bossz/blowergun.wav"); + sound_switchattacks = gi.soundindex("monsters/bossz/bswitch.wav"); + sound_plamsaballfly = gi.soundindex("monsters/bossz/bpbfly.wav"); + sound_plamsaballexplode = gi.soundindex("monsters/bossz/bpbexplode.wav"); + sound_plamsaballfire = gi.soundindex("monsters/bossz/bpbfire.wav"); + sound_taunt1 = gi.soundindex("monsters/bossz/btaunt1.wav"); + sound_taunt2 = gi.soundindex("monsters/bossz/btaunt2.wav"); + sound_taunt3 = gi.soundindex("monsters/bossz/btaunt3.wav"); +} + + +/*QUAKED monster_zboss (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_zboss (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + SP_monster_zboss_precache(); + + // Lazarus: special purpose skins + if ( self->style ) + { + PatchMonsterModel("models/monsters/bossz/mech/tris.md2"); + PatchMonsterModel("models/monsters/bossz/pilot/tris.md2"); + self->s.skinnum = self->style * 3; + } + + // precache some models and sounds + gi.modelindex("sprites/plasma1.sp2"); + gi.modelindex("models/objects/b_explode/tris.md2"); + gi.soundindex("items/empnuke/emp_trg.wav"); + + self->s.modelindex = gi.modelindex ("models/monsters/bossz/mech/tris.md2"); + self->s.modelindex2 = gi.modelindex ("models/monsters/bossz/pilot/tris.md2"); + self->s.modelindex3 = gi.modelindex ("models/monsters/bossz/grapple/tris.md2"); + + VectorSet (self->mins, -32, -74, -30); + VectorSet (self->maxs, 32, 50, 74); + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + self->monsterinfo.aiflags2 = AI2_MONREDUCEDDAMAGE; + self->monsterinfo.reducedDamageAmount = 0.25; + + if (skill->value == 0) + { + self->health = 3000; + } + else if (skill->value == 1) + { + self->health = 4500; + } + else if (skill->value == 2) + { + self->health = 6000; + } + else + { + self->health = 8000; + } + + self->gib_health = -700; + self->mass = 1000; + + self->pain = zboss_pain; + self->die = zboss_die; + + self->monsterinfo.stand = zboss_stand; + self->monsterinfo.walk = zboss_walk; + self->monsterinfo.run = zboss_run; + self->monsterinfo.attack = zboss_attack; + self->monsterinfo.melee = zboss_melee; + self->monsterinfo.sight = zboss_sight; + self->monsterinfo.idle = possibleBossTaunt; + + // Knightmare- added sparks and blood type + if (!self->blood_type) + self->blood_type = 2; // sparks + + self->common_name = "Titan"; + + gi.linkentity (self); + + self->monsterinfo.currentmove = &zboss_stand1; + self->monsterinfo.scale = MODEL_SCALE; + + walkmonster_start (self); +} + + + +/*QUAKED target_zboss_target +*/ + +void trigger_zboss (edict_t *self, edict_t *other, edict_t *activator) +{ + edict_t *boss = NULL; + + while ((boss = G_Find (boss, FOFS(targetname), self->target)) != NULL) + { + if (boss->health > 0) + { + VectorCopy( self->s.origin, boss->monsterinfo.shottarget ); + boss->monsterinfo.aiflags2 |= AI2_ONESHOTTARGET; + boss->monsterinfo.attack(boss); + } + } +} + + +void SP_target_zboss_target(edict_t *self) +{ + if (!self->target) + { + gi.dprintf("target_zboss_target does not have a target"); + G_FreeEdict (self); + return; + } + + self->movetype = MOVETYPE_NONE; + self->svflags |= SVF_NOCLIENT; + + self->solid = SOLID_NOT; + self->use = trigger_zboss; + + gi.linkentity (self); +} diff --git a/missionpack/z_boss.h b/missionpack/z_boss.h new file mode 100644 index 0000000..ab32d43 --- /dev/null +++ b/missionpack/z_boss.h @@ -0,0 +1,136 @@ +#ifndef Z_BOSS_H +#define Z_BOSS_H + +/* + Boss constants + +/zaero/models/monsters/bossz/mech/tris.md2 + +001-031 Idle1 (waves arms around menacingly) +032-056 Idle2 (grapple thing) + +057-066 RHook (raises weapon from Idle to fire Grappling Hook or Rockets) + - weapon arm rotates as it raises + +067-070 RCannon (raises weapon from Idle to fire Cannon) + +071-091 Attack1a (fires 7 Rockets) + - you can skip some frames if not firing all 7 rockets and jump to the reload sequence next + - (33, 50, 5) frame071 + - (27, 39, 5) frame074 + - (39, 39, 5) frame077 + - (27, 44, 5) frame080 + - (39, 44, 5) frame083 + - (29, 48, 5) frame086 + - (38, 48, 5) frame089 + +092-098 Attack1b (reloads rockets) + +099-106 Attack2a (fires Grappling Hook) + - (34, 24, 3) frame104 + +107-109 Attack2b (reels in Grappling Hook) + - loop as long as neccessary + - return hook to (34, 24, 5) approx. (arm is moving round) + +110-118 Attack2c (punch/swing, use at end of grapple attack2b) + +119-132 Attack3 (Cannon) + - spread is approx 50 degress wide + - (30, 44, 19) 25 degrees left of target, frame119 + - (32, 33, 14) 16 degrees left of target, frame121 + - (32, 45, 4) 8 degrees left of target, frame123 + - (32, 34, 2) towards target, frame125 + - (32, 49, -7) 8 degrees right of target, frame127 + - (34, 36, -6) 16 degrees right of target, frame129 + - (34, 36, -6) 16 degrees right of target, frame131 + +133-135 LCannon (lowers weapon from Cannon firing to Idle) +136-141 LHook (lowers weapon from Grappling Hook or Rocket firing to Idle) + +142-147 H2C (switches from Rocket firing to Cannon) +148-153 C2H (switches from Cannon firing to Grappling Hook or Rockets) +- use these to switch from one attack to another without resetting to Idle + +154-160 Walk1 (steps out from Idle on left foot) +161-169 Walk2 (steps forward on right foot) +170-176 Walk3 (steps forward on left foot) +177-184 Walk4 (steps to Idle on right foot) + +185-187 Pain1 (short) +188-192 Pain2 (medium) +193-217 Pain3 (very long) + +218-236 Death1 (falls over backwards) + +237-281 Death2 (head blown off) + - steps forward to gain balance + - rocket (25, 26, 26) frame249 + - rocket (20, 21, 16) frame250 + - rocket (30, 20, 17) frame251 + - rocket (17, 16, 8) frame252 + - rocket (30, 16, 10) frame253 + - rocket (25, 18, 0) frame254 + - rocket (30, 27, -17) frame255 + - cannon (33, 46, -9) 20 degrees right of target, frame257 + - cannon (37, 31, -3) 15 degrees right of target, frame258 + - cannon (24, 19, 21) 25 degrees left of target, frame264 + - grappling (28, -8, 35) straight up end of death2 seq. + (make grapple hook only occur 15% of the time) + + +/zaero/models/monsters/bossz/grapple/tris.md2 + +282-282 Grapple1 (shooting out) +283-283 Grapple2 (retracting) + +*/ + +#define FRAME_stand1start 1 +#define FRAME_stand1end 31 +#define FRAME_stand2start 32 +#define FRAME_stand2end 56 +#define FRAME_preHookStart 57 +#define FRAME_preHookEnd 66 +#define FRAME_preCannonStart 67 +#define FRAME_preCannonEnd 70 +#define FRAME_attack1aStart 71 +#define FRAME_attack1aEnd 91 +#define FRAME_attack1bStart 92 +#define FRAME_attack1bEnd 98 +#define FRAME_attack2aStart 99 +#define FRAME_attack2aEnd 106 +#define FRAME_attack2bStart 107 +#define FRAME_attack2bEnd 109 +#define FRAME_attack2cStart 110 +#define FRAME_attack2cEnd 118 +#define FRAME_attack3Start 119 +#define FRAME_attack3End 132 +#define FRAME_postCannonStart 133 +#define FRAME_postCannonEnd 135 +#define FRAME_postHookStart 136 +#define FRAME_postHookEnd 141 +#define FRAME_attackH2CStart 142 +#define FRAME_attackH2CEnd 147 +#define FRAME_attackC2HStart 148 +#define FRAME_attackC2HEnd 153 +#define FRAME_preWalkStart 154 +#define FRAME_preWalkEnd 160 +#define FRAME_walkStart 161 +#define FRAME_walkEnd 176 +#define FRAME_postWalkStart 177 +#define FRAME_postWalkEnd 184 +#define FRAME_pain1Start 185 +#define FRAME_pain1End 187 +#define FRAME_pain2Start 188 +#define FRAME_pain2End 192 +#define FRAME_pain3Start 193 +#define FRAME_pain3End 217 +#define FRAME_die1Start 218 +#define FRAME_die1End 236 +#define FRAME_die2Start 237 +#define FRAME_die2End 281 + +#define MODEL_SCALE 1.000 + +#endif diff --git a/missionpack/z_handler.c b/missionpack/z_handler.c new file mode 100644 index 0000000..49408c6 --- /dev/null +++ b/missionpack/z_handler.c @@ -0,0 +1,517 @@ +/* +============================================================================== + +handler handler + +============================================================================== +*/ + +#include "g_local.h" +#include "z_handler.h" + + + + +void handler_standWhatNext (edict_t *self); +void handler_standSitWhatNext (edict_t *self); +void handler_stand (edict_t *self); +void handler_attack (edict_t *self); +void hound_createHound(edict_t *self, float healthPercent); +void handler_ConvertToInfantry(edict_t *self); + +void hound_sight (edict_t *self, edict_t *other); +void infantry_sight (edict_t *self, edict_t *other); + +static int sound_attack; +static int sound_scratch; +static int sound_sitdown; +static int sound_standup; + + +void handler_sight (edict_t *self, edict_t *other) +{ + hound_sight (self, other); + infantry_sight (self, other); +} + +// +// STAND +// + +mframe_t handler_frames_stand1 [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL +}; +mmove_t handler_stand1 = {FRAME_stand1start, FRAME_stand1end, handler_frames_stand1, handler_standSitWhatNext}; + + +void handler_scratch (edict_t *self) +{ +// gi.sound (self, CHAN_VOICE, sound_scratch, 1, ATTN_NORM, 0); +} + + +mframe_t handler_frames_stand2 [] = +{ + ai_stand, 0, handler_scratch, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, +}; +mmove_t handler_stand2 = {FRAME_stand2start, FRAME_stand2end, handler_frames_stand2, handler_standSitWhatNext}; + + + +mframe_t handler_frames_stand3 [] = +{ + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, +}; +mmove_t handler_stand3 = {FRAME_stand3start, FRAME_stand3end, handler_frames_stand3, handler_standWhatNext}; + + +void handler_standup(edict_t *self) +{ +// gi.sound (self, CHAN_VOICE, sound_standup, 1, ATTN_NORM, 0); +} + + +mframe_t handler_frames_stand4 [] = +{ + ai_stand, 0, handler_standup, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + + ai_stand, 0, NULL, +}; +mmove_t handler_stand4 = {FRAME_stand4start, FRAME_stand4end, handler_frames_stand4, handler_standWhatNext}; + + + +void handler_sitdown(edict_t *self) +{ +// gi.sound (self, CHAN_VOICE, sound_sitdown, 1, ATTN_NORM, 0); +} + + +mframe_t handler_frames_stand5 [] = +{ + ai_stand, 0, handler_sitdown, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, + ai_stand, 0, NULL, +}; +mmove_t handler_stand5 = {FRAME_stand5start, FRAME_stand5end, handler_frames_stand5, handler_standSitWhatNext}; + + +/* + 00-30 Idle1 (sitting down) + 31-59 Idle2 (pat on head) + 60-89 Idle3 (standing) + 90-100 Stand (standing up from sitting) +101-110 Sit (sitting down from standing) +111-128 Restrain (handler lets go) +*/ +void handler_standWhatNext (edict_t *self) +{ + float r = random(); + + if (r < 0.90) + { + self->monsterinfo.currentmove = &handler_stand3; + } + else + { + self->monsterinfo.currentmove = &handler_stand5; + } +} + + +void handler_standSitWhatNext (edict_t *self) +{ + float r = random(); + + if (r < 0.70) + { + self->monsterinfo.currentmove = &handler_stand1; + } + else if (r < 0.85) + { + self->monsterinfo.currentmove = &handler_stand2; + } + else + { + self->monsterinfo.currentmove = &handler_stand4; + } +} + + +void handler_stand (edict_t *self) +{ + float r = random(); + + if (self->monsterinfo.currentmove != &handler_stand1 && + self->monsterinfo.currentmove != &handler_stand2 && + self->monsterinfo.currentmove != &handler_stand3 && + self->monsterinfo.currentmove != &handler_stand4 && + self->monsterinfo.currentmove != &handler_stand5) + { + self->monsterinfo.currentmove = &handler_stand3; + } +} + + + +// +// PAIN +// + +void handler_pain (edict_t *self, edict_t *other, float kick, int damage) +{ +// if (self->health < (self->max_health / 2)) +// self->s.skinnum = 1; +} + + +// +// ATTACK and MELEE +// + +void handler_createHound (edict_t *self) +{ + self->s.modelindex2 = 0; + hound_createHound(self, (self->health / 175.0)); +} + + +void CheckIdleLoop (edict_t *self) +{ + if (!self->powerarmor_time && self->spawnflags & 8) + { + self->powerarmor_time = level.time + (FRAMETIME * random() * 3); + } + + if (self->powerarmor_time > level.time) + { + self->s.frame -= 2; + } +} + +void CheckForEnemy (edict_t *self) +{ + if(self->enemy && (self->enemy->client || (self->enemy->svflags & SVF_MONSTER))) + { + self->powerarmor_time = 0; + return; + } + + if(self->powerarmor_time < level.time) + { + self->enemy = NULL; + handler_stand(self); + return; + } + + self->s.frame--; +} + +void StartCount (edict_t *self) +{ + self->powerarmor_time = level.time + 3; +} + +mframe_t handler_frames_attack1 [] = +{ + ai_run, 0, StartCount, + ai_run, 0, CheckForEnemy, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, CheckIdleLoop, + ai_charge, 0, NULL, + + ai_charge, 0, NULL, + ai_charge, 0, handler_createHound, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, + ai_charge, 0, NULL, +}; +mmove_t handler_move_attack1 = {FRAME_attack1Start, FRAME_attack1End, handler_frames_attack1, handler_ConvertToInfantry}; + + +void handler_attack (edict_t *self) +{ + gi.sound (self, CHAN_VOICE, sound_attack, 1, ATTN_NORM, 0); + + self->monsterinfo.currentmove = &handler_move_attack1; + + self->powerarmor_time = 0; +} + + + + + +/* +=== +Death Stuff Starts +=== +*/ + +void handler_dead (edict_t *self) +{ + // Lazarus: Stupid... if flies aren't set by M_FlyCheck, monster_think + // will cause us to come back here over and over and over + // until flies ARE set or monster is gibbed. + // This line fixes that: + self->nextthink = 0; + + VectorSet (self->mins, -16, -16, -24); + VectorSet (self->maxs, 16, 16, -8); + self->movetype = MOVETYPE_TOSS; + self->svflags |= SVF_DEADMONSTER; + self->nextthink = 0; + gi.linkentity (self); + M_FlyCheck (self); + + // Lazarus monster fade + if (world->effects & FX_WORLDSPAWN_CORPSEFADE) + { + self->think = FadeDieSink; + self->nextthink = level.time+corpse_fadetime->value; + } +} + + +void handler_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + self->health = 1; // can't die while together... +} + + +/* +=== +End Death Stuff +=== +*/ + +void SP_monster_infantry_precache(void); +void SP_monster_hound_precache(); + +void SP_monster_handler_precache(void) +{ + SP_monster_infantry_precache(); + SP_monster_hound_precache(); + + sound_attack = gi.soundindex("monsters/guard/hhattack.wav"); +/* + sound_scratch = gi.soundindex("monsters/guard/hhscratch.wav"); + sound_sitdown = gi.soundindex("monsters/guard/hhsitdown.wav"); + sound_standup = gi.soundindex("monsters/guard/hhstandup.wav"); +*/ +} + + +/*QUAKED monster_handler (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight +*/ +void SP_monster_handler (edict_t *self) +{ + if (deathmatch->value) + { + G_FreeEdict (self); + return; + } + + SP_monster_handler_precache(); + + // Lazarus: special purpose skins + if ( self->style ) + { + PatchMonsterModel("models/monsters/guard/handler/tris.md2"); + PatchMonsterModel("models/monsters/guard/hound/tris.md2"); + self->s.skinnum = self->style * 2; + } + + self->s.modelindex = gi.modelindex ("models/monsters/guard/handler/tris.md2"); + self->s.modelindex2 = gi.modelindex ("models/monsters/guard/hound/tris.md2"); + + /* + Handler + X = -36 to 3 + Y = -3 to 27 + Z = -24 to 28 + + Hound + X = -12 to 11 + Y = -30 to 30 + Z = -24 to 8 + */ + + VectorSet (self->mins, -32, -32, -24); + VectorSet (self->maxs, 32, 32, 32); + self->movetype = MOVETYPE_STEP; + self->solid = SOLID_BBOX; + + if (!self->health) + self->health = 175; + if (!self->gib_health) + self->gib_health = -50; + if (!self->mass) + self->mass = 250; + + self->pain = handler_pain; + self->die = handler_die; + + self->monsterinfo.stand = handler_stand; + self->monsterinfo.walk = handler_stand; + self->monsterinfo.run = handler_attack; + self->monsterinfo.attack = handler_attack; + self->monsterinfo.melee = NULL; + self->monsterinfo.sight = handler_sight; + self->monsterinfo.idle = NULL; + + // Lazarus + if (self->powerarmor) + { + if (self->powerarmortype == 1) + self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; + else + self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; + self->monsterinfo.power_armor_power = self->powerarmor; + } + + if (!self->monsterinfo.flies) + self->monsterinfo.flies = 0.40; + + self->common_name = "Enforcer with HellHound"; + + gi.linkentity (self); + + self->monsterinfo.currentmove = &handler_stand1; +/* if (self->health < 0) + { + mmove_t *deathmoves[] = {&infantry_move_death1, + &infantry_move_death2, + &infantry_move_death3, + NULL}; + M_SetDeath(self,(mmove_t **)&deathmoves); + }*/ + self->monsterinfo.scale = MODEL_SCALE; + + if (!(self->spawnflags & 16)) + { + level.total_monsters++; // add one for the hound which is created later :) + } + + walkmonster_start (self); +} diff --git a/missionpack/z_handler.h b/missionpack/z_handler.h new file mode 100644 index 0000000..abfc1de --- /dev/null +++ b/missionpack/z_handler.h @@ -0,0 +1,33 @@ +#ifndef Z_HANDLER_H +#define Z_HANDLER_H + +/* + 00-30 Idle1 (sitting down) + 31-59 Idle2 (pat on head) + 60-89 Idle3 (standing) + 90-100 Stand (standing up from sitting) +101-110 Sit (sitting down from standing) +111-128 Restrain (handler lets go) +*/ + +/* + Hound constants +*/ +#define FRAME_stand1start 0 +#define FRAME_stand1end 30 +#define FRAME_stand2start 31 +#define FRAME_stand2end 59 +#define FRAME_stand3start 60 +#define FRAME_stand3end 89 +#define FRAME_stand4start 90 +#define FRAME_stand4end 100 +#define FRAME_stand5start 101 +#define FRAME_stand5end 110 + +#define FRAME_attack1Start 111 +#define FRAME_attack1Sep 122 +#define FRAME_attack1End 128 + +#define MODEL_SCALE 1.000 + +#endif diff --git a/missionpack/z_hound.c b/missionpack/z_hound.c index 2b69e7c..d0bf4e2 100644 --- a/missionpack/z_hound.c +++ b/missionpack/z_hound.c @@ -43,26 +43,26 @@ void hound_sight (edict_t *self, edict_t *other) mframe_t hound_frames_stand1 [] = { - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 10 + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, // 10 - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL }; mmove_t hound_stand1 = {FRAME_stand1start, FRAME_stand1end, hound_frames_stand1, hound_stand}; @@ -70,29 +70,29 @@ mmove_t hound_stand1 = {FRAME_stand1start, FRAME_stand1end, hound_frames_stand1, mframe_t hound_frames_stand2 [] = { - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 10 + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, // 10 - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, - ai_stand, 0, NULL, // 20 + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, + ai_schoolStand, 0, NULL, // 20 - ai_stand, 0, NULL + ai_schoolStand, 0, NULL }; mmove_t hound_stand2 = {FRAME_stand2start, FRAME_stand2end, hound_frames_stand2, hound_stand}; @@ -101,13 +101,13 @@ mmove_t hound_stand2 = {FRAME_stand2start, FRAME_stand2end, hound_frames_stand2, void hound_stand (edict_t *self) { if (random() < 0.8) - { - self->monsterinfo.currentmove = &hound_stand1; - } - else - { - self->monsterinfo.currentmove = &hound_stand2; - } + { + self->monsterinfo.currentmove = &hound_stand1; + } + else + { + self->monsterinfo.currentmove = &hound_stand2; + } } // @@ -117,13 +117,13 @@ void hound_stand (edict_t *self) mframe_t hound_frames_run [] = { - ai_run, 60, NULL, - ai_run, 60, NULL, - ai_run, 40, NULL, - ai_run, 30, NULL, - ai_run, 30, NULL, - ai_run, 30, NULL, - ai_run, 40, NULL + ai_schoolRun, 60, NULL, + ai_schoolRun, 60, NULL, + ai_schoolRun, 40, NULL, + ai_schoolRun, 30, NULL, + ai_schoolRun, 30, NULL, + ai_schoolRun, 30, NULL, + ai_schoolRun, 40, NULL }; mmove_t hound_move_run = {FRAME_runStart, FRAME_runEnd, hound_frames_run, NULL}; @@ -131,7 +131,7 @@ mmove_t hound_move_run = {FRAME_runStart, FRAME_runEnd, hound_frames_run, NULL}; void hound_run (edict_t *self) { if (self->monsterinfo.aiflags & AI_STAND_GROUND) - hound_stand(self); + hound_stand(self); else self->monsterinfo.currentmove = &hound_move_run; } @@ -143,14 +143,14 @@ void hound_run (edict_t *self) mframe_t hound_frames_walk [] = { - ai_walk, 7, NULL, - ai_walk, 7, NULL, - ai_walk, 7, NULL, - ai_walk, 7, NULL, - ai_walk, 7, NULL, - ai_walk, 7, NULL, - ai_walk, 7, NULL, - ai_walk, 7, NULL + ai_schoolWalk, 7, NULL, + ai_schoolWalk, 7, NULL, + ai_schoolWalk, 7, NULL, + ai_schoolWalk, 7, NULL, + ai_schoolWalk, 7, NULL, + ai_schoolWalk, 7, NULL, + ai_schoolWalk, 7, NULL, + ai_schoolWalk, 7, NULL }; mmove_t hound_move_walk = {FRAME_walkStart, FRAME_walkEnd, hound_frames_walk, hound_walk}; @@ -241,29 +241,29 @@ void hound_bite2 (edict_t *self) mframe_t hound_frames_attack1 [] = { - ai_charge, 0, hound_launch, - ai_charge, 0, NULL, - ai_charge, 0, hound_bite, - ai_charge, 0, hound_bite2 + ai_schoolCharge, 0, hound_launch, + ai_schoolCharge, 0, NULL, + ai_schoolCharge, 0, hound_bite, + ai_schoolCharge, 0, hound_bite2 }; mmove_t hound_move_attack1 = {FRAME_attack1Start, FRAME_attack1End, hound_frames_attack1, hound_run}; mframe_t hound_frames_attack2 [] = { - ai_charge, 0, hound_launch, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, NULL, - ai_charge, 0, hound_bite, - ai_charge, 0, hound_bite2, - ai_charge, 0, hound_bite2, - ai_charge, 0, hound_bite2, - ai_charge, 0, NULL, + ai_schoolCharge, 0, hound_launch, + ai_schoolCharge, 0, NULL, + ai_schoolCharge, 0, NULL, + ai_schoolCharge, 0, NULL, + ai_schoolCharge, 0, NULL, + ai_schoolCharge, 0, NULL, + ai_schoolCharge, 0, NULL, + ai_schoolCharge, 0, NULL, + ai_schoolCharge, 0, hound_bite, + ai_schoolCharge, 0, hound_bite2, + ai_schoolCharge, 0, hound_bite2, + ai_schoolCharge, 0, hound_bite2, + ai_schoolCharge, 0, NULL, }; mmove_t hound_move_attack2 = {FRAME_attack2Start, FRAME_attack2End, hound_frames_attack2, hound_run}; @@ -271,13 +271,13 @@ mmove_t hound_move_attack2 = {FRAME_attack2Start, FRAME_attack2End, hound_frames void hound_attack (edict_t *self) { if (random() < 0.6) - { - self->monsterinfo.currentmove = &hound_move_attack1; - } - else - { - self->monsterinfo.currentmove = &hound_move_attack2; - } + { + self->monsterinfo.currentmove = &hound_move_attack1; + } + else + { + self->monsterinfo.currentmove = &hound_move_attack2; + } } @@ -482,6 +482,12 @@ Death Stuff Starts void hound_dead (edict_t *self) { + // Lazarus: Stupid... if flies aren't set by M_FlyCheck, monster_think + // will cause us to come back here over and over and over + // until flies ARE set or monster is gibbed. + // This line fixes that: + self->nextthink = 0; + VectorSet (self->mins, -16, -16, -24); VectorSet (self->maxs, 16, 16, -8); self->movetype = MOVETYPE_TOSS; @@ -491,7 +497,7 @@ void hound_dead (edict_t *self) M_FlyCheck (self); // Lazarus monster fade - if(world->effects & FX_WORLDSPAWN_CORPSEFADE) + if (world->effects & FX_WORLDSPAWN_CORPSEFADE) { self->think = FadeDieSink; self->nextthink = level.time+corpse_fadetime->value; @@ -590,16 +596,19 @@ void SP_monster_hound (edict_t *self) self->solid = SOLID_BBOX; self->yaw_speed = 30; - self->health = 175; - self->gib_health = -50; - self->mass = 250; + if (!self->health) + self->health = 175; + if (!self->gib_health) + self->gib_health = -50; + if (!self->mass) + self->mass = 250; self->pain = hound_pain; self->die = hound_die; -/* if (self->spawnflags & 0x8) + if (self->spawnflags & 0x8) { - self->monsterinfo.aiflags = AI_SCHOOLING; + self->monsterinfo.aiflags2 = AI2_SCHOOLING; } self->monsterinfo.zSchoolSightRadius = 500; @@ -609,7 +618,7 @@ void SP_monster_hound (edict_t *self) self->monsterinfo.zSpeedWalkMax = 3; self->monsterinfo.zSchoolDecayRate = 0.95; self->monsterinfo.zSchoolMinimumDistance = 100; -*/ + self->monsterinfo.stand = hound_stand; self->monsterinfo.walk = hound_walk; self->monsterinfo.run = hound_run; @@ -631,7 +640,8 @@ void SP_monster_hound (edict_t *self) self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; self->monsterinfo.power_armor_power = self->powerarmor; } - self->common_name = "Hound"; + + self->common_name = "HellHound"; gi.linkentity (self); @@ -640,3 +650,80 @@ void SP_monster_hound (edict_t *self) walkmonster_start (self); } + +void monster_think (edict_t *self); +qboolean monster_start (edict_t *self); +void hound_createHound (edict_t *self, float healthPercent) +{ + edict_t *hound; + + hound = G_Spawn(); + + //*hound = *self; + + hound->classname = "monster_hound"; + hound->s.modelindex = gi.modelindex ("models/monsters/guard/hound/tris.md2"); + VectorSet (hound->mins, -16, -16, -24); + VectorSet (hound->maxs, 16, 16, 24); + VectorCopy(self->s.origin, hound->s.origin); + VectorCopy(self->s.old_origin, hound->s.old_origin); + VectorCopy(self->s.angles, hound->s.angles); + hound->movetype = MOVETYPE_STEP; + hound->solid = SOLID_BBOX; + hound->takedamage = DAMAGE_YES; + hound->svflags |= SVF_MONSTER; + hound->svflags &= ~SVF_DEADMONSTER; + hound->s.renderfx |= RF_FRAMELERP; + hound->clipmask = MASK_MONSTERSOLID; + hound->deadflag = DEAD_NO; + hound->owner = self; + hound->yaw_speed = 30; + hound->enemy = self->enemy; + hound->ideal_yaw = self->ideal_yaw; + + hound->health = 175.0 * healthPercent; + hound->gib_health = -50; + hound->mass = 250; + + hound->pain = hound_pain; + hound->die = hound_die; + + hound->monsterinfo.stand = hound_stand; + hound->monsterinfo.walk = hound_walk; + hound->monsterinfo.run = hound_run; + hound->monsterinfo.attack = hound_jump; + hound->monsterinfo.melee = hound_attack; + hound->monsterinfo.sight = hound_sight; + hound->monsterinfo.idle = hound_stand; + hound->monsterinfo.checkattack = hound_checkattack; + + hound->monsterinfo.currentmove = &hound_move_handlerjump; + hound->monsterinfo.scale = MODEL_SCALE; + + hound->think = monster_think; + hound->nextthink = level.time + FRAMETIME; + + // Lazarus + hound->powerarmor = self->powerarmor; + if (hound->powerarmor) + { + if (hound->powerarmortype == 1) + hound->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; + else + hound->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; + hound->monsterinfo.power_armor_power = self->powerarmor; + } + + hound->monsterinfo.flies = self->monsterinfo.flies; + if (!hound->monsterinfo.flies) + hound->monsterinfo.flies = 0.60; + + hound->common_name = "HellHound"; + +// monster_start(hound); + + gi.linkentity (hound); + + // move the fucker now!!! + ai_move (hound, 20); +} diff --git a/missionpack/z_item.c b/missionpack/z_item.c new file mode 100644 index 0000000..aad1b57 --- /dev/null +++ b/missionpack/z_item.c @@ -0,0 +1,688 @@ +#include "g_local.h" + + +extern qboolean is_quad; +extern byte is_silenced; + +void playQuadSound(edict_t *ent); +void Weapon_Generic (edict_t *ent, + int FRAME_ACTIVATE_LAST, + int FRAME_FIRE_LAST, + int FRAME_IDLE_LAST, + int FRAME_DEACTIVATE_LAST, + int *pause_frames, + int *fire_frames, + void (*fire)(edict_t *ent)); +void NoAmmoWeaponChange (edict_t *ent); +void check_dodge (edict_t *self, vec3_t start, vec3_t dir, int speed); +void barrel_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf); + +void Grenade_Explode(edict_t *ent); +void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result); + +#ifdef USE_ZAERO_ITEMS_WEAPONS +void zCam_TrackEntity(struct edict_s *player, struct edict_s *track, qboolean playerVisiable, qboolean playerOffset); +void zCam_Stop(struct edict_s *player); +#endif // USE_ZAERO_ITEMS_WEAPONS + +void fire_empnuke(edict_t *ent, vec3_t center, int radius); + + +/* +====================================================================== + +misc_securitycamera + +This is where the visor locates too... + +====================================================================== +*/ +#ifdef USE_ZAERO_ITEMS_WEAPONS +void use_securitycamera (edict_t *self, edict_t *other, edict_t *activator) +{ + self->active = !self->active; +} + +#define CAMERA_FRAME_FIRST 0 +#define CAMERA_FRAME_LAST 59 +void securitycamera_think(edict_t *self) +{ + if (self->active) + { + self->s.frame++; + if (self->s.frame > CAMERA_FRAME_LAST) + self->s.frame = CAMERA_FRAME_FIRST; + } + + if (self->timeout > level.time) + { + self->s.effects |= EF_COLOR_SHELL; + self->s.renderfx |= RF_SHELL_GREEN; + } + else + { + self->s.effects &= ~EF_COLOR_SHELL; + self->s.renderfx &= ~RF_SHELL_GREEN; + } + + self->nextthink = level.time + FRAMETIME; +} + +void camera_pain(edict_t *self, edict_t *other, float kick, int damage) +{ + self->timeout = level.time + FRAMETIME * 2; +} + +void SP_misc_securitycamera(edict_t *self) +{ + vec3_t offset, forward, up; + + // no message? error + if (!self->message) + { + gi.error("misc_securitycamera w/o message"); + G_FreeEdict(self); + return; + } + + self->solid = SOLID_BBOX; + self->movetype = MOVETYPE_NONE; + self->s.modelindex = gi.modelindex("models/objects/camera/tris.md2"); + + // set the bounding box + VectorSet(self->mins, -16, -16, -32); + VectorSet(self->maxs, 16, 16, 0); + + // set the angle of direction + VectorCopy(self->mangle, self->move_angles); + VectorSet(self->s.angles, 0, self->mangle[YAW], 0); + + // get an offset + AngleVectors(self->s.angles, forward, NULL, up); + VectorSet(offset, 0, 0, 0); + VectorMA(offset, 8, forward, offset); + VectorMA(offset, -32, up, offset); + VectorAdd(self->s.origin, offset, self->move_origin); + + if (self->targetname) + { + self->use = use_securitycamera; + self->active = false; + } + else + { + self->active = true; + } + self->think = securitycamera_think; + self->nextthink = level.time + FRAMETIME; + + self->health = 1; + self->takedamage = DAMAGE_IMMORTAL; // health will not be deducted + self->pain = camera_pain; + + gi.linkentity(self); +} + +char *camera_statusbar = +"xv 26 yb -75 string \"Tracking %s\" " +// timer +"if 20 " +" xv 246 " +" num 3 21 " +" xv 296 " +" pic 20 " +"endif " +; + +void updateVisorHud(edict_t *ent) +{ + static char buf[1024]; + gi.WriteByte (svc_layout); +// sprintf(buf, camera_statusbar, ent->client->zCameraTrack->message); + Com_sprintf(buf, sizeof(buf), camera_statusbar, ent->client->zCameraTrack->message); + gi.WriteString(buf); +} + +void startVisorStatic(edict_t *ent) +{ + ent->client->zCameraStaticFramenum = level.time + FRAMETIME * 2; +} + +void startVisor(edict_t *ent, edict_t *e) +{ + // don't do anything if we're already at the destination camera + if (e == ent->client->zCameraTrack) + return; + + // no more time? + if (ent->client->pers.visorFrames <= 0) + { + gi.cprintf(ent, PRINT_HIGH, "No time left for visor\n"); + return; + } + + // look thru the camera + zCam_TrackEntity(ent, e, true, true); + + startVisorStatic(ent); + updateVisorHud(ent); + gi.unicast(ent, true); // reliably send to ent + ent->client->showscores = true; + + // play activation sound + gi.sound(ent, CHAN_AUTO, gi.soundindex("items/visor/act.wav"), 1, ATTN_NORM, 0); +} + +void stopCamera(edict_t *self) +{ + zCam_Stop(self); + self->client->showscores = false; + gi.sound(self, CHAN_AUTO, gi.soundindex("items/visor/deact.wav"), 1, ATTN_NORM, 0); +} + +edict_t *findNextCamera(edict_t *old) +{ + edict_t *e = NULL; + + // first of all, are there *any* cameras? + e = G_Find(NULL, FOFS(classname), "misc_securitycamera"); + if (e == NULL) + return NULL; + + // start with the current and try to find another good camera + e = old; + while(1) + { + e = G_Find(e, FOFS(classname), "misc_securitycamera"); + if (e == NULL) + continue; // loop back around + + if (e == old) + return e; + + if (!e->active) + continue; + + return e; + } + return NULL; +} + +void Use_Visor (edict_t *ent, gitem_t *item) +{ + if (ent->client->zCameraTrack == NULL) + { + edict_t *e = findNextCamera(NULL); + if (e == NULL) + { + gi.cprintf(ent, PRINT_HIGH, "No cameras are available\n"); + return; + } + + if (ent->client->pers.visorFrames == 0) + ent->client->pers.visorFrames = (sk_visor_time->value * 10); + startVisor(ent, e); + } + else + { + edict_t *e = findNextCamera(ent->client->zCameraTrack); + if (e != NULL && + e != ent->client->zCameraTrack) + { + ent->client->zCameraTrack = e; + // play sound + gi.sound(ent, CHAN_AUTO, gi.soundindex("items/visor/act.wav"), 1, ATTN_NORM, 0); + startVisorStatic(ent); + updateVisorHud(ent); + gi.unicast(ent, true); // reliably send to ent + } + } +} +#endif // USE_ZAERO_ITEMS_WEAPONS + + +/* +====================================================================== + +EMP Nuke + +====================================================================== +*/ +void weapon_EMPNuke_fire (edict_t *ent) +{ + fire_empnuke (ent, ent->s.origin, 1024); +// fire_empnuke (ent, ent->s.origin, sk_empnuke_radius->value); + + ent->client->pers.inventory[ent->client->ammo_index]--; + + if (ent->client->pers.inventory[ent->client->ammo_index]) + { + ent->client->weaponstate = WEAPON_ACTIVATING; + ent->client->ps.gunframe = 0; + } + else + { + NoAmmoWeaponChange (ent); + ChangeWeapon(ent); + } +} + + +void Weapon_EMPNuke (edict_t *ent) +{ + static int pause_frames[] = {25, 34, 43, 0}; + static int fire_frames[] = {16, 0}; + +#ifndef KMQUAKE2_ENGINE_MOD // Knightmare- no need to worry about overflows... + if (deathmatch->value) +#endif + { + if (ent->client->ps.gunframe == 0) + { + gi.sound(ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_act.wav"), 1, ATTN_NORM, 0); + } + else if (ent->client->ps.gunframe == 11) + { + gi.sound(ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_spin.wav"), 1, ATTN_NORM, 0); + } + else if (ent->client->ps.gunframe == 35) + { + gi.sound(ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_idle.wav"), 1, ATTN_NORM, 0); + } + } + + Weapon_Generic (ent, 9, 16, 43, 47, pause_frames, fire_frames, weapon_EMPNuke_fire); +} + + +void empnukeFinish (edict_t *ent) +{ +// gi.sound(ent, CHAN_VOICE, gi.soundindex("items/empnuke/empdie.wav"), 1, ATTN_NORM, 0); + G_FreeEdict(ent); +} + + +void empBlastAnim (edict_t *ent) +{ + ent->s.frame++; + ent->s.skinnum++; + + if (ent->s.frame > 5) + { + ent->svflags |= SVF_NOCLIENT; + ent->s.modelindex = 0; + ent->s.frame = 0; + ent->s.skinnum = 0; + + // ent->s.sound = gi.soundindex ("items/empnuke/empactive.wav"); + + ent->think = empnukeFinish; + ent->nextthink = level.time + 30; + } + else + { + ent->nextthink = level.time + FRAMETIME; + } +} + + +void fire_empnuke (edict_t *ent, vec3_t center, int radius) +{ + edict_t *empnuke; + +// gi.sound(ent, CHAN_VOICE, gi.soundindex("items/empnuke/empfire.wav"), 1, ATTN_NORM, 0); + gi.sound(ent, CHAN_VOICE, gi.soundindex("items/empnuke/emp_trg.wav"), 1, ATTN_NORM, 0); + + empnuke = G_Spawn(); + empnuke->owner = ent; + empnuke->dmg = radius; + VectorCopy(center, empnuke->s.origin); + empnuke->classname = "EMPNukeCenter"; +/// empnuke->svflags |= SVF_NOCLIENT; + empnuke->movetype = MOVETYPE_NONE; + empnuke->s.modelindex = gi.modelindex("models/objects/b_explode/tris.md2"); + empnuke->s.skinnum = 0; +// empnuke->s.renderfx = RF_TRANSLUCENT | RF_FULLBRIGHT; +// empnuke->s.renderfx = RF_TRANSLUCENT; + + empnuke->think = empBlastAnim; + empnuke->nextthink = level.time + FRAMETIME; + +// empnuke->think = G_FreeEdict; +// empnuke->nextthink = level.time + 30; + gi.linkentity (empnuke); + +// gi.sound(empnuke, CHAN_VOICE, gi.soundindex("items/empnuke/emp_exp.wav"), 1, ATTN_NORM, 0); +} + + +qboolean EMPNukeCheck (edict_t *ent, vec3_t pos) +{ + edict_t *check = NULL; + + while ((check = G_Find (check, FOFS(classname), "EMPNukeCenter")) != NULL) + { + vec3_t v; + + if (check->owner != ent) + { + VectorSubtract (check->s.origin, pos, v); + if (VectorLength(v) <= check->dmg) + { + return true; + } + } + } + return false; +} + + +/* +====================================================================== + +Plasma Shield + +====================================================================== +*/ +#ifdef USE_ZAERO_ITEMS_WEAPONS +void PlasmaShield_die (edict_t *self) +{ +#ifndef KMQUAKE2_ENGINE_MOD // Knightmare- no need to worry about overflows... + if (deathmatch->value) +#endif + { + gi.sound(self, CHAN_VOICE, gi.soundindex("items/plasmashield/psdie.wav"), 1, ATTN_NORM, 0); + } + G_FreeEdict(self); +} + + +void PlasmaShield_killed (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) +{ + PlasmaShield_die(self); +} + + +void Use_PlasmaShield (edict_t *ent, gitem_t *item) +{ + int ammoIdx = ITEM_INDEX(item); + edict_t *PlasmaShield; + vec3_t forward, right, up, frontbottomleft, backtopright; + + if(!ent->client->pers.inventory[ammoIdx]) + { + return; + } + + if(EMPNukeCheck(ent, ent->s.origin)) + { + gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); + return; + } + + if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) + ent->client->pers.inventory[ammoIdx]--; + +#ifndef KMQUAKE2_ENGINE_MOD // Knightmare- no need to worry about overflows... + if (deathmatch->value) +#endif + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("items/plasmashield/psfire.wav"), 1, ATTN_NORM, 0); + } + + PlasmaShield = G_Spawn(); +// PlasmaShield->owner = ent; + PlasmaShield->classname = "PlasmaShield"; + PlasmaShield->movetype = MOVETYPE_PUSH; + PlasmaShield->solid = SOLID_BBOX; + PlasmaShield->s.modelindex = gi.modelindex("sprites/plasmashield.sp2"); + PlasmaShield->s.effects |= EF_POWERSCREEN; + PlasmaShield->s.sound = gi.soundindex ("items/plasmashield/psactive.wav"); + + AngleVectors (ent->client->v_angle, forward, right, up); + vectoangles (forward, PlasmaShield->s.angles); + + VectorMA (ent->s.origin, 50, forward, PlasmaShield->s.origin); + + // fudge the bbox + VectorScale(forward, 10, frontbottomleft); + VectorMA(frontbottomleft, -30, right, frontbottomleft); + VectorMA(frontbottomleft, -30, up, frontbottomleft); + + VectorScale(forward, 5, backtopright); + VectorMA(backtopright, 30, right, backtopright); + VectorMA(backtopright, 50, up, backtopright); + + ClearBounds (PlasmaShield->mins, PlasmaShield->maxs); + + AddPointToBounds (frontbottomleft, PlasmaShield->mins, PlasmaShield->maxs); + AddPointToBounds (backtopright, PlasmaShield->mins, PlasmaShield->maxs); + + PlasmaShield->health = PlasmaShield->max_health = sk_plasmashield_health->value; // was 4000 + PlasmaShield->die = PlasmaShield_killed; + PlasmaShield->takedamage = DAMAGE_YES; + + PlasmaShield->think = PlasmaShield_die; + PlasmaShield->nextthink = level.time + sk_plasmashield_life->value; // was 10 + + gi.linkentity (PlasmaShield); +} +#endif + + +/* +====================================================================== + +misc_crate + +====================================================================== +*/ + +void setupCrate (edict_t *self) +{ + self->solid = SOLID_BBOX; + self->movetype = MOVETYPE_FALLFLOAT; +// self->movetype = MOVETYPE_STEP; + + if (!self->mass) + self->mass = 400; + + self->touch = barrel_touch; + self->think = M_droptofloor; + self->nextthink = level.time + 2 * FRAMETIME; + + gi.linkentity(self); +} + +void SP_misc_crate (edict_t *self) +{ + // setup specific to this size + self->s.modelindex = gi.modelindex("models/objects/crate/crate64.md2"); + VectorSet (self->mins, -32, -32, 0); + VectorSet (self->maxs, 32, 32, 64); + + // generic crate setup + setupCrate(self); +} + +void SP_misc_crate_medium (edict_t *self) +{ + // setup specific to this size + self->s.modelindex = gi.modelindex("models/objects/crate/crate48.md2"); + VectorSet (self->mins, -24, -24, 0); + VectorSet (self->maxs, 24, 24, 48); + + // generic crate setup + setupCrate(self); +} + +void SP_misc_crate_small (edict_t *self) +{ + // setup specific to this size + self->s.modelindex = gi.modelindex("models/objects/crate/crate32.md2"); + VectorSet (self->mins, -16, -16, 0); + VectorSet (self->maxs, 16, 16, 32); + + // generic crate setup + setupCrate(self); +} + +/* +====================================================================== + +misc_seat + +====================================================================== +*/ + +void SP_misc_seat (edict_t *self) +{ + self->s.modelindex = gi.modelindex("models/objects/seat/tris.md2"); + VectorSet(self->mins, -16, -16, 0); + VectorSet(self->maxs, 16, 16, 40); + + // make this pushable + setupCrate(self); +} + +/* +====================================================================== + +misc_commdish + +====================================================================== +*/ + +void Anim_CommDish(edict_t *self) +{ + self->s.frame++; + + if(self->s.frame >= 98) + { + self->s.frame = 98; + } + else + { + self->nextthink = level.time + FRAMETIME; + } +} + +void Use_CommDish (edict_t *ent, edict_t *other, edict_t *activator) +{ + ent->nextthink = level.time + FRAMETIME; + ent->think = Anim_CommDish; + ent->use = NULL; + gi.sound (ent, CHAN_AUTO, gi.soundindex ("misc/commdish.wav"), 1, ATTN_NORM, 0); +} + +void SP_misc_commdish (edict_t *self) +{ + if (deathmatch->value) + { // auto-remove for deathmatch + G_FreeEdict (self); + return; + } + + self->solid = SOLID_BBOX; + self->movetype = MOVETYPE_STEP; + + self->model = "models/objects/satdish/tris.md2"; + self->s.modelindex = gi.modelindex (self->model); + VectorSet (self->mins, -100, -100, 0); + VectorSet (self->maxs, 100, 100, 275); + + self->monsterinfo.aiflags = AI_NOSTEP; + + self->think = M_droptofloor; + self->nextthink = level.time + 2 * FRAMETIME; + self->use = Use_CommDish; + + gi.linkentity (self); +} + +/* +====================================================================== + +func_barrier + +====================================================================== +*/ + +qboolean thruBarrier (edict_t *targ, edict_t *inflictor) +{ + trace_t tr; + edict_t *e = inflictor; + while(e) + { + tr = gi.trace(e->s.origin, NULL, NULL, targ->s.origin, e, MASK_SHOT); + if (!tr.ent || tr.fraction >= 1.0) + return false; + + if (tr.ent == targ) + return false; + + if (tr.ent->classname && Q_stricmp(tr.ent->classname, "func_barrier") == 0) + return true; + + if(e == tr.ent) + break; + + e = tr.ent; + } + return false; +} + +void barrier_think (edict_t *self) +{ + if (self->timeout > level.time) + { + self->svflags &= ~SVF_NOCLIENT; + } + else + { + self->svflags |= SVF_NOCLIENT; + } + + self->nextthink = level.time + FRAMETIME; +} + +void barrier_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + self->timeout = level.time + FRAMETIME * 2; + if (self->damage_debounce_time < level.time) + { + gi.sound (self, CHAN_AUTO, gi.soundindex("weapons/lashit.wav"), 1, ATTN_NORM, 0); + self->damage_debounce_time = level.time + FRAMETIME * 2; + } +} +void barrier_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + if (other == world) + return; + + self->timeout = level.time + FRAMETIME * 2; + if (self->touch_debounce_time < level.time) + { + gi.sound (self, CHAN_AUTO, gi.soundindex("weapons/lashit.wav"), 1, ATTN_NORM, 0); + self->touch_debounce_time = level.time + FRAMETIME * 2; + } + +} + +void SP_func_barrier (edict_t *self) +{ + self->solid = SOLID_BBOX; + self->movetype = MOVETYPE_NONE; + self->s.modelindex = gi.modelindex("models/objects/wall/tris.md2"); + self->svflags = SVF_NOCLIENT; + self->s.effects = EF_BFG; + + self->think = barrier_think; + self->nextthink = level.time + FRAMETIME; + self->touch = barrier_touch; + self->health = 1; + self->takedamage = DAMAGE_IMMORTAL; // health will not be deducted + self->pain = barrier_pain; + + gi.linkentity(self); +} diff --git a/missionpack/z_sentien.c b/missionpack/z_sentien.c index 241f5f3..7647d96 100644 --- a/missionpack/z_sentien.c +++ b/missionpack/z_sentien.c @@ -828,8 +828,8 @@ void sentien_attack(edict_t *self) void sentien_fend_ready (edict_t *self) { - //if (self->monsterinfo.aiflags & AI_REDUCEDDAMAGE) - // return; + if (self->monsterinfo.aiflags2 & AI2_REDUCEDDAMAGE) + return; self->monsterinfo.pausetime = level.time + 1; } @@ -838,11 +838,12 @@ void sentien_fend_hold (edict_t *self) if (level.time >= self->monsterinfo.pausetime) { self->monsterinfo.aiflags &= ~AI_HOLD_FRAME; - // self->monsterinfo.aiflags &= ~AI_REDUCEDDAMAGE; + self->monsterinfo.aiflags2 &= ~AI2_REDUCEDDAMAGE; } else { - self->monsterinfo.aiflags |= (AI_HOLD_FRAME);// | AI_REDUCEDDAMAGE); + self->monsterinfo.aiflags |= AI_HOLD_FRAME; + self->monsterinfo.aiflags2 |= AI2_REDUCEDDAMAGE; } } @@ -1219,11 +1220,11 @@ void SP_monster_sentien(edict_t *self) SP_monster_sentien_precache(); - if(!self->health) + if (!self->health) self->health = 900; - if(!self->gib_health) + if (!self->gib_health) self->gib_health = -425; - if(!self->mass) + if (!self->mass) self->mass = 500; // Lazarus: special purpose skins @@ -1253,15 +1254,15 @@ void SP_monster_sentien(edict_t *self) self->monsterinfo.sight = NULL; self->monsterinfo.idle = NULL; - //self->monsterinfo.reducedDamageAmount = 0.85; + self->monsterinfo.reducedDamageAmount = 0.85; // Lazarus if (!self->blood_type) - self->blood_type = 2; //sparks + self->blood_type = 2; // sparks else - self->fogclip |= 2; //custom bloodtype flag + self->fogclip |= 2; // custom bloodtype flag - if(self->powerarmor) + if (self->powerarmor) { if (self->powerarmortype == 1) self->monsterinfo.power_armor_type = POWER_ARMOR_SCREEN; @@ -1269,7 +1270,7 @@ void SP_monster_sentien(edict_t *self) self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD; self->monsterinfo.power_armor_power = self->powerarmor; } - if(!self->monsterinfo.flies) + if (!self->monsterinfo.flies) self->monsterinfo.flies = 0.10; self->common_name = "Sentien"; // end Lazarus @@ -1281,12 +1282,12 @@ void SP_monster_sentien(edict_t *self) create_sentien_laser(self); - if(skill->value == 2) + if (skill->value == 2) { self->flash->dmg *= 1.5; self->yaw_speed *= 1.5; } - else if(skill->value >= 3) + else if (skill->value >= 3) { self->flash->dmg *= 2.5; self->yaw_speed *= 2; @@ -1297,5 +1298,3 @@ void SP_monster_sentien(edict_t *self) walkmonster_start(self); } - - diff --git a/missionpack/z_trigger.c b/missionpack/z_trigger.c new file mode 100644 index 0000000..ea6ef8b --- /dev/null +++ b/missionpack/z_trigger.c @@ -0,0 +1,109 @@ +#include "g_local.h" + +/* +====================================================================== + +trigger_laser + +====================================================================== +*/ + +/*QUAKED trigger_laser (1 0 0) (-16 -16 -16) (16 16 16) TRIGGER_MULTIPLE +Laser-type trigger +"wait" "x" where x is the delay before reactivation +"target" target to trigger +"message" message to center print +"delay" delay before trigger +*/ + +#define TRIGGER_MULTIPLE 1 +void trigger_laser_on (edict_t *self); +void trigger_laser_think (edict_t *self) +{ + vec3_t start; + vec3_t end; + trace_t tr; + int count = 8; + + self->nextthink = level.time + FRAMETIME; + + VectorCopy (self->s.origin, start); + VectorMA (start, 2048, self->movedir, end); + tr = gi.trace (start, NULL, NULL, end, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER); + + if (!tr.ent) + return; + + // if we hit something that's not a monster or player + if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client)) + { + if (self->spawnflags & 0x80000000) + { + self->spawnflags &= ~0x80000000; + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_LASER_SPARKS); + gi.WriteByte (count); + gi.WritePosition (tr.endpos); + gi.WriteDir (tr.plane.normal); + gi.WriteByte (self->s.skinnum); + gi.multicast (tr.endpos, MULTICAST_PVS); + } + } + else + { + // trigger + G_UseTargets (self, tr.ent); + + if (self->spawnflags & TRIGGER_MULTIPLE) + { + // hide for a time + self->svflags |= SVF_NOCLIENT; + self->nextthink = level.time + self->wait; + self->think = trigger_laser_on; + } + else + { + // remove self + G_FreeEdict(self); + } + } + + VectorCopy (tr.endpos, self->s.old_origin); +} + +void trigger_laser_on (edict_t *self) +{ + self->svflags &= ~SVF_NOCLIENT; + self->think = trigger_laser_think; + trigger_laser_think(self); +} + +void SP_trigger_laser (edict_t *self) +{ + // if no target + if (!self->target) + { + gi.dprintf("trigger_laser without target\n"); + G_FreeEdict(self); + return; + } + + // if no wait, set default + if (!self->wait) + { + self->wait = 4; + } + + G_SetMovedir (self->s.angles, self->movedir); + self->s.skinnum = 0xf2f2f0f0; // colour + self->s.frame = 2; // diameter + self->movetype = MOVETYPE_NONE; + self->solid = SOLID_NOT; + self->s.renderfx |= RF_BEAM|RF_TRANSLUCENT; + self->s.modelindex = 1; + self->spawnflags |= 0x80000000; + self->think = trigger_laser_on; + self->nextthink = level.time + 0.1; + self->svflags |= SVF_NOCLIENT; + gi.linkentity (self); +} diff --git a/missionpack/z_weapon.c b/missionpack/z_weapon.c new file mode 100644 index 0000000..af16be5 --- /dev/null +++ b/missionpack/z_weapon.c @@ -0,0 +1,1571 @@ +#include "g_local.h" +#include "m_player.h" + +extern qboolean is_quad; +extern byte is_silenced; + +void playQuadSound(edict_t *ent); +void Weapon_Generic (edict_t *ent, + int FRAME_ACTIVATE_LAST, + int FRAME_FIRE_LAST, + int FRAME_IDLE_LAST, + int FRAME_DEACTIVATE_LAST, + int *pause_frames, + int *fire_frames, + void (*fire)(edict_t *ent)); +void NoAmmoWeaponChange (edict_t *ent); +void check_dodge (edict_t *self, vec3_t start, vec3_t dir, int speed); + +void Grenade_Explode(edict_t *ent); +void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result); + +#ifdef USE_ZAERO_ITEMS_WEAPONS +void fire_sconnan (edict_t *self); +void fire_sconnanEffects (edict_t *self); +#endif // USE_ZAERO_ITEMS_WEAPONS + +const int SC_MAXFIRETIME = 5; // in seconds... +const int SC_BASEDAMAGE = 10; // minimum damage +const int SC_DAMGERANGE = 990; // maximum damaged range (max damage possible is SC_BASEDAMAGE + SC_DAMGERANGE) +const int SC_MAXRADIUS = 500; // maximum blast radius +const int SC_MAXCELLS = 100; // maximum number of cells + +#if 0 +vec_t VectorLengthSquared (vec3_t v) +{ + int i; + float length; + + length = 0; + for (i=0 ; i< 3 ; i++) + length += v[i]*v[i]; + + return length; +} + +void angleToward (edict_t *self, vec3_t point, float speed) +{ + vec3_t forward; + float yaw = 0.0; + float vel = 0.0; + vec3_t delta; + vec3_t destAngles; + VectorSubtract(point, self->s.origin, delta); + vectoangles(delta, destAngles); + self->ideal_yaw = destAngles[YAW]; + self->yaw_speed = speed; + M_ChangeYaw(self); + yaw = self->s.angles[YAW]; + self->ideal_yaw = destAngles[PITCH]; + self->s.angles[YAW] = self->s.angles[PITCH]; + M_ChangeYaw(self); + self->s.angles[PITCH] = self->s.angles[YAW]; + self->s.angles[YAW] = yaw; + AngleVectors (self->s.angles, forward, NULL, NULL); + vel = VectorLength(self->velocity); + VectorScale(forward, vel, self->velocity); +} +#endif + +#define MAXROTATION 20 + +/* + Laser Trip Bombs +*/ +// spawnflags +#define CHECK_BACK_WALL 1 + +// variables +#define TBOMB_DELAY 1.0 +#define TBOMB_TIMEOUT 180 +#define TBOMB_DAMAGE 150 +#define TBOMB_RADIUS_DAMAGE 384 +#define TBOMB_HEALTH 100 +#define TBOMB_SHRAPNEL 5 +#define TBOMB_SHRAPNEL_DMG 15 +#define TBOMB_MAX_EXIST 25 + +#ifdef USE_ZAERO_ITEMS_WEAPONS +void shrapnel_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + // do damage if we can + if (!other->takedamage) + return; + + if (VectorCompare(ent->velocity, vec3_origin)) + return; + + T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, + plane->normal, sk_tbomb_shrapnel_damage->value, 8, 0, MOD_TRIPBOMB); + G_FreeEdict(ent); +} + +void TripBomb_Explode (edict_t *ent) +{ + vec3_t origin; + int i = 0; + + T_RadiusDamage(ent, ent->owner ? ent->owner : ent, ent->dmg, ent->enemy, ent->dmg_radius, MOD_TRIPBOMB); + + VectorMA (ent->s.origin, -0.02, ent->velocity, origin); + + gi.WriteByte (svc_temp_entity); + if (ent->waterlevel) + { + if (ent->groundentity) + gi.WriteByte (TE_GRENADE_EXPLOSION_WATER); + else + gi.WriteByte (TE_ROCKET_EXPLOSION_WATER); + } + else + { + if (ent->groundentity) + gi.WriteByte (TE_GRENADE_EXPLOSION); + else + gi.WriteByte (TE_ROCKET_EXPLOSION); + } + gi.WritePosition (origin); + gi.multicast (ent->s.origin, MULTICAST_PHS); + + // throw off some debris + for (i = 0; i < sk_tbomb_shrapnel->value; i++) + { + edict_t *sh = G_Spawn(); + vec3_t forward, right, up; + sh->classname = "shrapnel"; + sh->movetype = MOVETYPE_BOUNCE; + sh->solid = SOLID_BBOX; + sh->s.effects |= EF_GRENADE; + sh->s.modelindex = gi.modelindex("models/objects/shrapnel/tris.md2"); + sh->owner = ent->owner; + VectorSet (sh->avelocity, 300, 300, 300); + VectorCopy(ent->s.origin, sh->s.origin); + AngleVectors (ent->s.angles, forward, right, up); + VectorScale(forward, 500, forward); + VectorMA(forward, crandom()*500, right, forward); + VectorMA(forward, crandom()*500, up, forward); + VectorCopy(forward, sh->velocity); + sh->touch = shrapnel_touch; + sh->think = G_FreeEdict; + sh->nextthink = level.time + 3.0 + crandom() * 1.5; + } + + G_FreeEdict(ent); +} + +void tripbomb_laser_think (edict_t *self) +{ + vec3_t start; + vec3_t end; + vec3_t delta; + trace_t tr; + int count = 8; + + self->nextthink = level.time + FRAMETIME; + + if (level.time > self->timeout) + { + // play a sound + //gi.sound(self, CHAN_VOICE, gi.soundindex("weapons/ired/las_trig.wav"), 1, ATTN_NORM, 0); + + // blow up + self->chain->think = TripBomb_Explode; + self->chain->nextthink = level.time + FRAMETIME; + G_FreeEdict(self); + return; + } + + // randomly phase out or EMPNuke is in effect + if (EMPNukeCheck(self, self->s.origin) || random() < 0.1) + { + self->svflags |= SVF_NOCLIENT; + return; + } + + self->svflags &= ~SVF_NOCLIENT; + VectorCopy (self->s.origin, start); + VectorMA (start, 2048, self->movedir, end); + tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT); + + if (!tr.ent) + return; + + VectorSubtract(tr.endpos, self->move_origin, delta); + if (VectorCompare(self->s.origin, self->move_origin)) + { + // we haven't done anything yet + VectorCopy(tr.endpos, self->move_origin); + if (self->spawnflags & 0x80000000) + { + self->spawnflags &= ~0x80000000; + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_LASER_SPARKS); + gi.WriteByte (count); + gi.WritePosition (tr.endpos); + gi.WriteDir (tr.plane.normal); + gi.WriteByte (self->s.skinnum); + gi.multicast (tr.endpos, MULTICAST_PVS); + } + } + else if (VectorLength(delta) > 1.0) + { + // play a sound + //gi.sound(self, CHAN_VOICE, gi.soundindex("weapons/ired/las_trig.wav"), 1, ATTN_NORM, 0); + + // blow up + self->chain->think = TripBomb_Explode; + self->chain->nextthink = level.time + FRAMETIME; + G_FreeEdict(self); + return; + } + VectorCopy(self->move_origin, self->s.old_origin); +} + +void tripbomb_laser_on (edict_t *self) +{ + self->svflags &= ~SVF_NOCLIENT; + self->think = tripbomb_laser_think; + + // play a sound + gi.sound(self, CHAN_VOICE, gi.soundindex("weapons/ired/las_arm.wav"), 1, ATTN_NORM, 0); + tripbomb_laser_think(self); + //gi.positioned_sound(self->s.old_origin, self, CHAN_AUTO, gi.soundindex("weapons/ired/las_tink.wav"), 1, ATTN_NORM, 0); +} + +void create_tripbomb_laser (edict_t *bomb) +{ + // create the laser + edict_t *laser = G_Spawn(); + bomb->chain = laser; + laser->classname = "laser trip bomb laser"; + VectorCopy(bomb->s.origin, laser->s.origin); + VectorCopy(bomb->s.origin, laser->move_origin); + VectorCopy(bomb->s.angles, laser->s.angles); + G_SetMovedir (laser->s.angles, laser->movedir); + laser->owner = bomb; + laser->s.skinnum = 0xb0b1b2b3; // <- faint purple 0xf3f3f1f1 <-blue red-> 0xf2f2f0f0; + laser->s.frame = 2; + laser->movetype = MOVETYPE_NONE; + laser->solid = SOLID_NOT; + laser->s.renderfx |= RF_BEAM|RF_TRANSLUCENT; + laser->s.modelindex = 1; + laser->chain = bomb; + laser->spawnflags |= 0x80000001; + laser->think = tripbomb_laser_on; + laser->nextthink = level.time + FRAMETIME; + laser->svflags |= SVF_NOCLIENT; + laser->timeout = level.time + TBOMB_TIMEOUT; + gi.linkentity (laser); +} + +void use_tripbomb (edict_t *self, edict_t *other, edict_t *activator) +{ + if (self->chain) + { + // we already have a laser, remove it + G_FreeEdict(self->chain); + self->chain = NULL; + } + else + // create the laser + create_tripbomb_laser(self); +} + +void turnOffGlow (edict_t *self) +{ + self->s.effects &= ~EF_COLOR_SHELL; + self->s.renderfx &= ~RF_SHELL_GREEN; + self->think = NULL; + self->nextthink = 0; +} + +void tripbomb_pain (edict_t *self, edict_t *other, float kick, int damage) +{ + // play the green glow sound + //gi.sound(self, CHAN_VOICE, gi.soundindex("weapons/ired/las_glow.wav"), 1, ATTN_NORM, 0); + + // turn on the glow + self->damage_debounce_time = level.time + 0.2; + + // if we don't have a think function, then turn this thing on + if (self->think == NULL) + { + self->s.effects |= EF_COLOR_SHELL; + self->s.renderfx |= RF_SHELL_GREEN; + self->nextthink = self->damage_debounce_time; + self->think = turnOffGlow; + } +} + +void tripbomb_think (edict_t *self) +{ + if (self->chain == NULL) + { + // check whether we need to create the laser + if (self->timeout < level.time) + { + create_tripbomb_laser(self); + } + } + + // do we need to show damage? + if (self->damage_debounce_time > level.time) + { + self->s.effects |= EF_COLOR_SHELL; + self->s.renderfx |= RF_SHELL_GREEN; + } + else + { + self->s.effects &= ~EF_COLOR_SHELL; + self->s.renderfx &= ~RF_SHELL_GREEN; + } + + self->nextthink = level.time + FRAMETIME; +} + +void setupBomb (edict_t *bomb, char *classname, float damage, float damage_radius) +{ + bomb->classname = classname; + VectorSet(bomb->mins, -8, -8, -8); + VectorSet(bomb->maxs, 8, 8, 8); + bomb->solid = SOLID_BBOX; + bomb->movetype = MOVETYPE_NONE; + bomb->s.modelindex = gi.modelindex("models/objects/ired/tris.md2"); + bomb->radius_dmg = damage; + bomb->dmg = damage; + bomb->dmg_radius = damage_radius; + bomb->health = 1; + bomb->takedamage = DAMAGE_IMMORTAL; // health will not be deducted + bomb->pain = tripbomb_pain; +} + +void removeOldest () +{ + edict_t *oldestEnt = NULL; + edict_t *e = NULL; + int count = 0; + + while (1) + { + e = G_Find(e, FOFS(classname), "ired"); + if (e == NULL) // no more + break; + + count++; + + if (oldestEnt == NULL || + e->timestamp < oldestEnt->timestamp) + { + oldestEnt = e; + } + } + + // do we have too many? + if (count > TBOMB_MAX_EXIST && oldestEnt != NULL) + { + // get this tbomb to explode + oldestEnt->think = TripBomb_Explode; + oldestEnt->nextthink = level.time + FRAMETIME; + G_FreeEdict(oldestEnt->chain); + } +} + +qboolean fire_lasertripbomb (edict_t *self, vec3_t start, vec3_t dir, float timer, float damage, float damage_radius, qboolean quad) +{ + // trace a line + trace_t tr; + vec3_t endPos; + vec3_t _dir; + edict_t *bomb = NULL; + edict_t *laser = NULL; + + VectorScale(dir, 64, _dir); + VectorAdd(start, _dir, endPos); + + // trace ahead, looking for a wall + tr = gi.trace(start, NULL, NULL, endPos, self, MASK_SHOT); + if (tr.fraction == 1.0) + { + // not close enough + //gi.cprintf(self, PRINT_HIGH, "Not close enough to a wall"); + return false; + } + + if (Q_stricmp(tr.ent->classname, "worldspawn") != 0) + { + //gi.cprintf(self, PRINT_HIGH, "Hit something other than a wall"); + return false; + } + + // create the bomb + bomb = G_Spawn(); + //VectorCopy(tr.endpos, bomb->s.origin); + VectorMA(tr.endpos, 3, tr.plane.normal, bomb->s.origin); + vectoangles(tr.plane.normal, bomb->s.angles); + bomb->owner = self; + setupBomb(bomb, "ired", damage, damage_radius); + gi.linkentity(bomb); + + bomb->timestamp = level.time; + bomb->timeout = level.time + timer; + bomb->nextthink = level.time + FRAMETIME; + bomb->think = tripbomb_think; + + // remove the oldest trip bomb + removeOldest(); + + // play a sound + gi.sound(self, CHAN_VOICE, gi.soundindex("weapons/ired/las_set.wav"), 1, ATTN_NORM, 0); + return true; +} + +void weapon_lasertripbomb_fire (edict_t *ent) +{ + if (ent->client->ps.gunframe == 10) + { + vec3_t offset; + vec3_t forward; + vec3_t start; + int damage = sk_tbomb_damage->value; + float radius = sk_tbomb_radius->value; + if (is_quad) + damage *= 4; + + // place the trip bomb + VectorSet(offset, 0, 0, ent->viewheight * 0.75); + AngleVectors (ent->client->v_angle, forward, NULL, NULL); + VectorAdd(ent->s.origin, offset, start); + + if (fire_lasertripbomb(ent, start, forward, TBOMB_DELAY, damage, radius, is_quad)) + { + ent->client->pers.inventory[ent->client->ammo_index] -= 1; + + // switch models + ent->client->ps.gunindex = gi.modelindex("models/weapons/v_ired/hand.md2"); + + // play quad sound + playQuadSound(ent); + } + } + else if (ent->client->ps.gunframe == 15) + { + // switch models back + int mi = gi.modelindex("models/weapons/v_ired/tris.md2"); + if (ent->client->ps.gunindex != mi) + { + ent->client->ps.gunindex = mi; + // go back to get another trip bomb + ent->client->ps.gunframe = 0; + return; + } + } + else if (ent->client->ps.gunframe == 6) + { + ent->client->ps.gunframe = 16; + return; + } + + ent->client->ps.gunframe++; +} + +void Weapon_LaserTripBomb (edict_t *ent) +{ + static int pause_frames[] = {24, 33, 43, 0}; + static int fire_frames[] = {6, 10, 15, 0}; + + const int deactivateFirst = 44; + const int deactivateLast = 48; + const int idleFirst = 16; + const int idleLast = 43; + const int fireFirst = 7; + const int fireLast = 15; + const int activateFirst = 0; + const int activateLast = 6; + + if (ent->client->weaponstate == WEAPON_DROPPING) + { + if (ent->client->ps.gunframe == deactivateLast) + { + ChangeWeapon (ent); + return; + } + + ent->client->ps.gunframe++; + return; + } + + if (ent->client->weaponstate == WEAPON_ACTIVATING) + { + if (ent->client->ps.gunframe == activateLast) + { + ent->client->weaponstate = WEAPON_READY; + ent->client->ps.gunframe = idleFirst; + return; + } + + ent->client->ps.gunframe++; + return; + } + + if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING)) + { + ent->client->weaponstate = WEAPON_DROPPING; + ent->client->ps.gunframe = deactivateFirst; + return; + } + + if (ent->client->weaponstate == WEAPON_READY) + { + if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) + { + ent->client->latched_buttons &= ~BUTTON_ATTACK; + if(ent->client->pers.inventory[ent->client->ammo_index]) + { + ent->client->ps.gunframe = fireFirst; + ent->client->weaponstate = WEAPON_FIRING; + + // start the animation + ent->client->anim_priority = ANIM_ATTACK; + if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) + { + ent->s.frame = FRAME_crattak1-1; + ent->client->anim_end = FRAME_crattak9; + } + else + { + ent->s.frame = FRAME_attack1-1; + ent->client->anim_end = FRAME_attack8; + } + } + else + { + if (level.time >= ent->pain_debounce_time) + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); + ent->pain_debounce_time = level.time + 1; + } + NoAmmoWeaponChange (ent); + } + } + else + { + if (ent->client->ps.gunframe == idleLast) + { + ent->client->ps.gunframe = idleFirst; + return; + } + + if (pause_frames) + { + int n = 0; + for (n = 0; pause_frames[n]; n++) + { + if (ent->client->ps.gunframe == pause_frames[n]) + { + if (rand()&15) + return; + } + } + } + + ent->client->ps.gunframe++; + return; + } + } + + if (ent->client->weaponstate == WEAPON_FIRING) + { + int n = 0; + for (n = 0; fire_frames[n]; n++) + { + if (ent->client->ps.gunframe == fire_frames[n]) + { + weapon_lasertripbomb_fire(ent); + break; + } + } + + if (!fire_frames[n]) + ent->client->ps.gunframe++; + + if (ent->client->ps.gunframe == idleFirst+1) + ent->client->weaponstate = WEAPON_READY; + } +} + +void SP_misc_lasertripbomb (edict_t *bomb) +{ + // precache + gi.soundindex("weapons/ired/las_set.wav"); + gi.soundindex("weapons/ired/las_arm.wav"); + //gi.soundindex("weapons/ired/las_tink.wav"); + //gi.soundindex("weapons/ired/las_trig.wav"); + //gi.soundindex("weapons/ired/las_glow.wav"); + gi.modelindex("models/objects/shrapnel/tris.md2"); + gi.modelindex("models/objects/ired/tris.md2"); + + if (bomb->spawnflags & CHECK_BACK_WALL) + { + vec3_t forward, endPos; + trace_t tr; + // look backwards toward a wall + AngleVectors (bomb->s.angles, forward, NULL, NULL); + VectorMA(bomb->s.origin, -64.0, forward, endPos); + tr = gi.trace(bomb->s.origin, NULL, NULL, endPos, bomb, MASK_SOLID); + VectorCopy(tr.endpos, bomb->s.origin); + vectoangles(tr.plane.normal, bomb->s.angles); + } + + // set up ourself + setupBomb(bomb, "misc_ired", sk_tbomb_damage->value, sk_tbomb_radius->value); + + if (bomb->targetname) + { + bomb->use = use_tripbomb; + } + else + { + bomb->think = create_tripbomb_laser; + bomb->nextthink = level.time + TBOMB_DELAY; + } + gi.linkentity(bomb); +} +#endif // USE_ZAERO_ITEMS_WEAPONS + +/* +====================================================================== + +Sonic Cannon + +====================================================================== +*/ +#ifdef USE_ZAERO_ITEMS_WEAPONS +void weapon_sc_fire (edict_t *ent) +{ + int maxfiretime = sk_soniccannon_maxfiretime->value; + + if (!(ent->client->buttons & BUTTON_ATTACK)) + { + ent->client->ps.gunframe++; + + if(ent->client->weapon_sound && ent->client->ps.gunframe < 18) + { + ent->client->ps.gunframe = 18; + } + } + else + { + if(EMPNukeCheck(ent, ent->s.origin)) + { + gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); + + ent->client->ps.gunframe = 18; + ent->client->weapon_sound = 0; + ent->weaponsound_time = 0; + + ent->dmg_radius = 0; + ent->client->startFireTime = 0; + return; + } + + if(!ent->client->startFireTime) + { + ent->client->startFireTime = level.time; + } + else if(level.time - ent->client->startFireTime >= maxfiretime) + { + ent->client->ps.gunframe = 17; + } + else + { + int old_cells = (int)ent->dmg_radius; + ent->dmg_radius = ((level.time - ent->client->startFireTime) / maxfiretime) * sk_soniccannon_maxcells->value; + + if(old_cells < (int)ent->dmg_radius) + { + old_cells = (int)ent->dmg_radius - old_cells; + + if(ent->client->pers.inventory[ent->client->ammo_index] < old_cells) + { + ent->dmg_radius -= (old_cells - ent->client->pers.inventory[ent->client->ammo_index]); + ent->client->pers.inventory[ent->client->ammo_index] = 0; + } + else + { + ent->client->pers.inventory[ent->client->ammo_index] -= old_cells; + } + } + } + + if(!ent->client->pers.inventory[ent->client->ammo_index]) + { + ent->client->ps.gunframe = 17; + + if (level.time >= ent->pain_debounce_time) + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); + ent->pain_debounce_time = level.time + 1; + } + NoAmmoWeaponChange (ent); + } + else + { + if(ent->weaponsound_time < level.time) + { + ent->client->weapon_sound = gi.soundindex("weapons/sonic/sc_fire.wav"); + } + } + + fire_sconnanEffects (ent); + + ent->client->ps.gunframe++; + if (ent->client->ps.gunframe == 18 && (level.time - ent->client->startFireTime) < maxfiretime && ent->client->pers.inventory[ent->client->ammo_index]) + ent->client->ps.gunframe = 12; + } + + if (ent->client->ps.gunframe == 18) + { + ent->client->weapon_sound = 0; + ent->weaponsound_time = 0; + + if(EMPNukeCheck(ent, ent->s.origin)) + { + gi.sound (ent, CHAN_AUTO, gi.soundindex("items/empnuke/emp_missfire.wav"), 1, ATTN_NORM, 0); + } + else + { + if (!is_silenced) + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/sonic/sc_cool.wav"), 1, ATTN_NORM, 0); + else + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/sonic/sc_cool.wav"), 0.4, ATTN_NORM, 0); + + if(ent->dmg_radius) + { + fire_sconnan (ent); + } + } + + ent->dmg_radius = 0; + ent->client->startFireTime = 0; + } +} + + +void Weapon_SonicCannon (edict_t *ent) +{ + static int pause_frames[] = {32, 42, 52, 0}; + static int fire_frames[] = {12, 13, 14, 15, 16, 17, 0}; + + if (ent->client->ps.gunframe == 0) + { + #ifndef KMQUAKE2_ENGINE_MOD // Knightmare- no need to worry about overflows... + if (deathmatch->value) + #endif + { + if (!is_silenced) + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/sonic/sc_act.wav"), 1, ATTN_NORM, 0); + else + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/sonic/sc_act.wav"), 0.4, ATTN_NORM, 0); + } + ent->weaponsound_time = 0; + ent->client->startFireTime = 0; + ent->dmg_radius = 0; + } + else if (ent->client->ps.gunframe == 53) + { + #ifndef KMQUAKE2_ENGINE_MOD // Knightmare- no need to worry about overflows... + if (deathmatch->value) + #endif + { + if (!is_silenced) + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/sonic/sc_dact.wav"), 1, ATTN_NORM, 0); + else + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/sonic/sc_dact.wav"), 0.4, ATTN_NORM, 0); + } + } + else if((ent->client->buttons & BUTTON_ATTACK) && ent->weaponsound_time == 0) + { + ent->weaponsound_time = level.time + 0.4; + + if (!is_silenced) + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/sonic/sc_warm.wav"), 1, ATTN_NORM, 0); + else + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/sonic/sc_warm.wav"), 0.4, ATTN_NORM, 0); + } + + Weapon_Generic (ent, 6, 22, 52, 57, pause_frames, fire_frames, weapon_sc_fire); +} + + + +void SpawnDamage (int type, vec3_t origin, vec3_t normal, int damage); + +void fire_sconnanEffects (edict_t *self) +{ + vec3_t start, end; + vec3_t forward, right; + vec3_t offset, v; + trace_t tr; + + AngleVectors (self->client->v_angle, forward, right, NULL); + + VectorScale (forward, -3, self->client->kick_origin); + self->client->kick_angles[0] = -3; + + VectorSet(offset, 0, 7, self->viewheight-8); + P_ProjectSource (self->client, self->s.origin, offset, forward, right, start); + + VectorMA (start, WORLD_SIZE, forward, end); // was 8192 + + tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT|CONTENTS_SLIME|CONTENTS_LAVA); + + VectorMA (tr.endpos, -5, forward, end); + + VectorSet(v, crandom() * 10 - 20, crandom() * 10 - 20, crandom() * 10 - 20); + SpawnDamage(TE_SHIELD_SPARKS, end, v, 0); +} + + + +void scexplode_think (edict_t *self) +{ + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_ROCKET_EXPLOSION); + gi.WritePosition (self->s.origin); + gi.multicast (self->s.origin, MULTICAST_PHS); + + G_FreeEdict (self); +} + + +void fire_sconnan (edict_t *self) +{ + vec3_t start, end, explodepos; + vec3_t forward, right, up; + vec3_t offset; + trace_t tr; + float damage, radius; + + damage = self->dmg_radius / sk_soniccannon_maxcells->value; + radius = damage * sk_soniccannon_radius->value; + damage = sk_soniccannon_damage->value + (damage * sk_soniccannon_damage2->value); + + AngleVectors (self->client->v_angle, forward, right, up); + + VectorScale (forward, -3, self->client->kick_origin); + self->client->kick_angles[0] = -3; + + VectorSet(offset, 0, 7, self->viewheight-8); + P_ProjectSource (self->client, self->s.origin, offset, forward, right, start); + + VectorMA (start, WORLD_SIZE, forward, end); // was 8192 + + tr = gi.trace (start, NULL, NULL, end, self, MASK_SHOT|CONTENTS_SLIME|CONTENTS_LAVA); + + if ((tr.ent != self) && (tr.ent->takedamage)) + { + T_Damage (tr.ent, self, self, forward, tr.endpos, tr.plane.normal, damage, 0, 0, MOD_SONICCANNON); + } + + T_RadiusDamagePosition (tr.endpos, self, self, damage, tr.ent, radius, MOD_SONICCANNON); + + VectorMA (tr.endpos, -5, forward, end); + + gi.WriteByte (svc_temp_entity); + gi.WriteByte (TE_ROCKET_EXPLOSION); + gi.WritePosition (end); + gi.multicast (self->s.origin, MULTICAST_PHS); + + damage -= 100; + radius = 0.1; + + while (damage > 0) + { + edict_t *explode; + + VectorMA (end, (50 * crandom()) - 5, forward, explodepos); + VectorMA (explodepos, (50 * crandom()) - 5, right, explodepos); + VectorMA (explodepos, (50 * crandom()) - 5, up, explodepos); + + explode = G_Spawn(); + VectorCopy (explodepos, explode->s.origin); + + explode->classname = "sconnanExplode"; + explode->nextthink = level.time + radius; + explode->think = scexplode_think; + + radius += 0.1; + damage -= 100; + } + + // play quad damage sound + playQuadSound(self); +} +#endif // USE_ZAERO_ITEMS_WEAPONS + + + +/* +====================================================================== + +Flares + +====================================================================== +*/ +#define FLASH_RANGE 256.0 +void FoundTarget (edict_t *self); + +void flare_flash(edict_t *ent) +{ + edict_t *target = NULL; + + // flash + while (1) + { + float dist; + float ratio; + float dot; + vec3_t delta; + vec3_t forward; + + // get the next entity near us + target = findradius (target, ent->s.origin, FLASH_RANGE); + if (target == NULL) + break; + if (!target->client && !(target->svflags & SVF_MONSTER)) + continue; + if (target->deadflag) + continue; + if (!visible(ent, target)) + continue; + // if (!infront(target, ent)) + // continue; + + // what's the distance, so that closer get's more + VectorSubtract (ent->s.origin, target->s.origin, delta); + dist = VectorLength (delta); + ratio = 1 - (dist/FLASH_RANGE); + if (ratio < 0) + ratio = 0; + + // looking to the side get's less + AngleVectors (target->s.angles, forward, NULL, NULL); + VectorNormalize (delta); + dot = Z_MAX(0.0, DotProduct(delta, forward)); + ratio *= dot;// * 1.25; + + // set the flash counter + if (target->client) + { + target->client->flashTime += ratio*25; + if (target->client->flashTime > 25) + target->client->flashTime = 25; + target->client->flashBase = 30; + + if (deathmatch->value && + // !target->client->pers.gl_polyblend && + !(((int)zdmflags->value) & ZDM_NO_GL_POLYBLEND_DAMAGE)) + T_Damage(target, ent, ent->owner, vec3_origin, target->s.origin, vec3_origin, (int)(10.0*ratio), 0, 0, MOD_GL_POLYBLEND); + } + else if ((target->svflags & SVF_MONSTER) && strcmp(target->classname, "monster_zboss") != 0) + { + target->monsterinfo.flashTime = + Z_MAX(target->monsterinfo.flashTime, ratio*150); // a little bit more advantageous + target->monsterinfo.flashBase = 50; + if (target->enemy == NULL) + { + target->enemy = ent->owner; + FoundTarget(target); + } + } + } +} + + +void flare_think(edict_t *self) +{ + edict_t *target = NULL; + edict_t *closestEnt = NULL; + float closestDist = 0.0; + + // on our last leg? + if (level.time > self->timeout) + { + self->s.effects &= ~EF_ROCKET; + self->think = G_FreeEdict; + self->nextthink = level.time + 4.0; + self->s.frame = 0; + self->s.sound = 0; + return; + } + + self->s.frame++; + + if (self->s.frame > 14) + self->s.frame = 5; + + // hissing sound + self->s.sound = gi.soundindex ("weapons/flare/flarehis.wav"); + + // do the visual thing + flare_flash(self); + + // next frame + self->nextthink = level.time + FRAMETIME; +} + +void fire_flare (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage) +{ + edict_t *flare; + vec3_t adir; + vec3_t up; + + vectoangles (dir, adir); + AngleVectors (adir, NULL, NULL, up); + + flare = G_Spawn(); + VectorCopy (start, flare->s.origin); + VectorCopy (dir, flare->movedir); + vectoangles (dir, flare->s.angles); + VectorScale (dir, speed, flare->velocity); + VectorMA (flare->velocity, 200 + crandom() * 10.0, up, flare->velocity); + flare->movetype = MOVETYPE_BOUNCE; + flare->clipmask = MASK_SHOT; + flare->solid = SOLID_BBOX; + flare->s.effects = EF_ROCKET; + VectorSet(flare->mins, -4, -4, -4); + VectorSet(flare->maxs, 4, 4, 4); + flare->s.modelindex = gi.modelindex("models/objects/flare/tris.md2"); + flare->owner = self; +// flare->timeout = level.time + sk_flare_life->value; + flare->timeout = level.time + 8000/speed; + flare->nextthink = level.time + 1.0; + flare->think = flare_think; + flare->dmg = damage; + flare->radius_dmg = radius_damage; + flare->dmg_radius = damage_radius; + flare->classname = "flare"; + + if (self->client) + check_dodge (self, flare->s.origin, dir, speed); + + gi.linkentity (flare); +} + +#ifdef USE_ZAERO_ITEMS_WEAPONS +void Weapon_FlareLauncher_Fire (edict_t *ent) +{ + vec3_t offset, start; + vec3_t forward, right; + + AngleVectors (ent->client->v_angle, forward, right, NULL); + + VectorSet(offset, 8, 8, ent->viewheight-8); + P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); + fire_flare(ent, start, forward, sk_flaregun_damage->value, sk_flaregun_speed->value, sk_flaregun_radius->value, sk_flaregun_rdamage->value); + + ent->client->ps.gunframe++; + + PlayerNoise(ent, start, PNOISE_WEAPON); + + // play quad sound + playQuadSound(ent); + + if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) + ent->client->pers.inventory[ent->client->ammo_index]--; + + // play shooting sound + if (!is_silenced) + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/flare/shoot.wav"), 1, ATTN_NORM, 0); + else + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/flare/shoot.wav"), 0.4, ATTN_NORM, 0); +} + +void Weapon_FlareGun (edict_t *ent) +{ + static int pause_frames[] = {15, 25, 35, 0}; + static int fire_frames[] = {8, 0}; + + Weapon_Generic (ent, 5, 14, 44, 48, pause_frames, fire_frames, Weapon_FlareLauncher_Fire); +} +#endif // USE_ZAERO_ITEMS_WEAPONS + +/* +====================================================================== + +Sniper Rifle + +====================================================================== +*/ +#ifdef USE_ZAERO_ITEMS_WEAPONS +void fire_sniper_bullet (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick) +{ + trace_t tr; + vec3_t end, s; + edict_t *ignore = self; + int i=0; + + VectorMA (start, WORLD_SIZE, aimdir, end); // was 8192 + VectorCopy(start, s); + while (i<256) // Knightmare- prevent infinite loop, was 1 + { + tr = gi.trace (s, NULL, NULL, end, ignore, MASK_SHOT_NO_WINDOW); + if (tr.fraction >= 1.0) + return; + + // if we hit a plasmashield, then pass thru it + if (Q_stricmp(tr.ent->classname, "PlasmaShield") == 0) + { + ignore = tr.ent; + VectorCopy(tr.endpos, s); + } + else + break; + i++; + } + + gi.WriteByte (svc_temp_entity); + if (gi.pointcontents(tr.endpos) & MASK_WATER) + { + if (tr.plane.normal[2] > 0.7) + gi.WriteByte (TE_GRENADE_EXPLOSION_WATER); + else + gi.WriteByte (TE_ROCKET_EXPLOSION_WATER); + } + else + { + if (tr.plane.normal[2] > 0.7) + gi.WriteByte (TE_GRENADE_EXPLOSION); + else + gi.WriteByte (TE_ROCKET_EXPLOSION); + } + gi.WritePosition (tr.endpos); + gi.multicast (tr.endpos, MULTICAST_PHS); + + if (tr.ent->takedamage) + T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_NO_ARMOR, MOD_SNIPERRIFLE); +} + +void weapon_sniperrifle_fire (edict_t *ent) +{ + vec3_t forward, right; + vec3_t offset, start; + int damage; + int kick; + + if (deathmatch->value) + { // normal damage is too extreme in dm + damage = sk_sniperrifle_damage_dm->value; // 150 + kick = sk_sniperrifle_kick_dm->value; // 300 + } + else + { + damage = sk_sniperrifle_damage->value; // 250 + kick = sk_sniperrifle_kick->value; // 400 + } + + if (is_quad) + { + damage *= 4; + kick *= 4; + } + + AngleVectors (ent->client->v_angle, forward, right, NULL); + // centre the shot + VectorSet(offset, 0, 0, ent->viewheight); + VectorAdd(ent->s.origin, offset, start); + fire_sniper_bullet(ent, start, forward, damage, kick); + + if (!is_silenced) + gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/sniper/fire.wav"), 1, ATTN_NORM, 0); + else + gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/sniper/fire.wav"), 0.4, ATTN_NORM, 0); + + PlayerNoise(ent, start, PNOISE_WEAPON); + + // play quad sound + playQuadSound(ent); + + VectorScale (forward, -20, ent->client->kick_origin); + ent->client->kick_angles[0] = -2; + ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity; +} + +//#define SNIPER_CHARGE_TIME 30 +void Weapon_SniperRifle(edict_t *ent) +{ + /* + Activate/Deactivate + 0 - 8 : Activate + 9 - 18 : Fire + 19 - 27 : Idle 1 + 28 - 36 : Idle 2 + 37 - 41 : Deactivate + + Zoom + 0 - 1 Zoom + Hold 1 while zoomed + */ + const static int activateStart = 0; + const static int activateEnd = 8; + const static int deactivateStart = 37; + const static int deactivateEnd = 41; + const static int spFov = 15; + const static int dmFov = 30; + + if (ent->client->weaponstate == WEAPON_DROPPING) + { + ent->client->sniperFramenum = 0; + if (ent->client->ps.gunframe == deactivateStart) + { + // back to old fov + ent->client->ps.fov = 90; + #ifndef KMQUAKE2_ENGINE_MOD // Knightmare- no need to worry about overflows... + if (deathmatch->value) + #endif + gi.sound(ent, CHAN_WEAPON2, gi.soundindex("weapons/sniper/snip_bye.wav"), 1, ATTN_NORM, 0); + } + else if (ent->client->ps.gunframe == deactivateEnd) + { + ChangeWeapon(ent); + return; + } + + ent->client->ps.gunframe++; + return; + } + + if (ent->client->weaponstate == WEAPON_ACTIVATING) + { + if (ent->client->ps.gunframe == activateStart) + { + // play the activation sound + #ifndef KMQUAKE2_ENGINE_MOD // Knightmare- no need to worry about overflows... + if (deathmatch->value) + #endif + gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/sniper/snip_act.wav"), 1, ATTN_NORM, 0); + } + else if (ent->client->ps.gunframe == activateEnd) + { + ent->client->weaponstate = WEAPON_READY; + ent->client->ps.gunindex = (deathmatch->value ? + gi.modelindex("models/weapons/v_sniper/dmscope/tris.md2") : + gi.modelindex("models/weapons/v_sniper/scope/tris.md2") ); + ent->client->ps.gunframe = 0; + ent->client->ps.fov = (deathmatch->value ? dmFov : spFov); + ent->client->sniperFramenum = level.framenum + (sk_sniper_charge_time->value * 10); // SNIPER_CHARGE_TIME + return; + } + + ent->client->ps.gunframe++; + return; + } + + if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING)) + { + // back to other gun model + ent->client->ps.gunindex = gi.modelindex("models/weapons/v_sniper/tris.md2"); + ent->client->weaponstate = WEAPON_DROPPING; + ent->client->ps.gunframe = deactivateStart; + return; + } + + if (ent->client->weaponstate == WEAPON_READY) + { + ent->client->ps.gunindex = (deathmatch->value ? + gi.modelindex("models/weapons/v_sniper/dmscope/tris.md2") : + gi.modelindex("models/weapons/v_sniper/scope/tris.md2") ); + + ent->client->ps.fov = (deathmatch->value ? dmFov : spFov); + + // beep if the sniper frame num is a multiple of 10 + if (ent->client->sniperFramenum >= level.framenum) + { + if ((ent->client->sniperFramenum - level.framenum) % 10 == 1) + gi.sound(ent, CHAN_WEAPON2, gi.soundindex("weapons/sniper/beep.wav"), 1, ATTN_NORM, 0); + } + + if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) + { + if (level.framenum >= ent->client->sniperFramenum) + { + ent->client->latched_buttons &= ~BUTTON_ATTACK; + if ((!ent->client->ammo_index) || + ( ent->client->pers.inventory[ent->client->ammo_index] >= ent->client->pers.weapon->quantity)) + { + ent->client->weaponstate = WEAPON_FIRING; + + // start the animation + ent->client->anim_priority = ANIM_ATTACK; + if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) + { + ent->s.frame = FRAME_crattak1-1; + ent->client->anim_end = FRAME_crattak9; + } + else + { + ent->s.frame = FRAME_attack1-1; + ent->client->anim_end = FRAME_attack8; + } + } + else + { + if (level.time >= ent->pain_debounce_time) + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); + ent->pain_debounce_time = level.time + 1; + } + NoAmmoWeaponChange (ent); + } + } + } + } + + if (ent->client->weaponstate == WEAPON_FIRING) + { + ent->client->ps.gunindex = (deathmatch->value ? + gi.modelindex("models/weapons/v_sniper/dmscope/tris.md2") : + gi.modelindex("models/weapons/v_sniper/scope/tris.md2") ); + + ent->client->ps.fov = (deathmatch->value ? dmFov : spFov); + //if (ent->client->quad_framenum > level.framenum) + // gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); + + // fire + weapon_sniperrifle_fire(ent); + + // start recharge + ent->client->weaponstate = WEAPON_READY; + ent->client->sniperFramenum = level.framenum + (sk_sniper_charge_time->value * 10); // SNIPER_CHARGE_TIME; + } +} +#endif // USE_ZAERO_ITEMS_WEAPONS + +/* +====================================================================== + +Armageddon 2000 + +====================================================================== +*/ +#ifdef USE_ZAERO_ITEMS_WEAPONS +void weapon_a2k_exp_think(edict_t *self) +{ + self->s.frame++; + self->s.skinnum++; + + if (self->s.frame == 6) + { + G_FreeEdict(self); + return; + } + self->nextthink = level.time + FRAMETIME; +} + +void Z_RadiusDamageVisible(edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, int mod) +{ + float points; + edict_t *ent = NULL; + vec3_t v; + vec3_t dir; + + while ((ent = findradius(ent, inflictor->s.origin, radius)) != NULL) + { + if (ent == ignore) + continue; + if (!ent->takedamage) + continue; + if (!visible(inflictor, ent)) + continue; + + VectorAdd (ent->mins, ent->maxs, v); + VectorMA (ent->s.origin, 0.5, v, v); + VectorSubtract (inflictor->s.origin, v, v); + points = damage - 0.5 * VectorLength (v); + if (ent == attacker) + points = points * 0.5; + if (points > 0) + { + if (CanDamage (ent, inflictor)) + { + VectorSubtract (ent->s.origin, inflictor->s.origin, dir); + T_Damage (ent, inflictor, attacker, dir, inflictor->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, mod); + } + } + } +} + + +//#define A2K_FRAMENUM 50 +void weapon_a2k_fire (edict_t *ent) +{ + if (ent->client->ps.gunframe == 14) + { + ent->client->a2kFramenum = level.framenum + (sk_a2k_detonate_time->value * 10); // A2K_FRAMENUM; + ent->client->pers.inventory[ent->client->ammo_index]--; + ent->client->ps.gunframe++; + + // start scream sound + //ent->client->weapon_sound = gi.soundindex("weapons/a2k/countdn.wav"); + gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/a2k/countdn.wav"), 1, ATTN_NORM, 0); + //gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/a2k/ak_trig.wav"), 1, ATTN_NORM, 0); + + // play quad sound + playQuadSound(ent); + } + else if (ent->client->a2kFramenum == level.framenum) + { + // boom + edict_t *exp = NULL; + edict_t *e = NULL; + float damage = sk_a2k_damage->value; // was 2500 + float dmg_radius = sk_a2k_radius->value; // was 512 + + // play quad sound + playQuadSound(ent); + if (is_quad) + { + damage *= 4; + dmg_radius *= 4; + } + // do some damage + T_RadiusDamage(ent, ent, damage, NULL, dmg_radius, MOD_A2K); + + // ok, now, do who ever's visible within 1024 units + Z_RadiusDamageVisible(ent, ent, damage, NULL, dmg_radius * 2, MOD_A2K); + + exp = G_Spawn(); + exp->classname = "A2K Explosion"; + exp->solid = SOLID_NOT; + exp->movetype = MOVETYPE_NONE; + VectorClear(exp->mins); + VectorClear(exp->maxs); + VectorCopy(ent->s.origin, exp->s.origin); + exp->s.modelindex = gi.modelindex("models/objects/b_explode/tris.md2"); + exp->s.frame = 0; + exp->s.skinnum = 6; + exp->think = weapon_a2k_exp_think; + exp->nextthink = level.time + FRAMETIME; + gi.linkentity(exp); + gi.positioned_sound(exp->s.origin, exp, CHAN_AUTO, gi.soundindex("weapons/a2k/ak_exp01.wav"), 1, ATTN_NORM, 0); + ent->client->ps.gunframe++; + ent->client->weapon_sound = 0; + return; + } + else if (ent->client->ps.gunframe == 19) + { + // don't increase the gunframe + return; + } +} + +void Weapon_A2k (edict_t *ent) +{ + /* + 00-09 Active + 10-19 Boom (14 actual fire frame) + 20-29 Idle1 + 30-39 Idle2 + 40-49 Idle3 + 50-55 Away + */ + static int pause_frames[] = {20, 30, 40, 0}; + static int fire_frames[] = {14, 19, 0}; + + Weapon_Generic (ent, 9, 19, 49, 55, pause_frames, fire_frames, weapon_a2k_fire); +} +#endif // USE_ZAERO_ITEMS_WEAPONS + + +/* +====================================================================== + + Push + + 0 - Start push + 4 - Contact + 8 - End Push + +====================================================================== +*/ +#if 0 +qboolean push_hit (edict_t *self, vec3_t start, vec3_t aim, int damage, int kick) +{ + trace_t tr; + vec3_t end; + vec3_t v; + edict_t *e = NULL; + + //see if enemy is in range + VectorMA(start, 64, aim, end); + tr = gi.trace(start, NULL, NULL, end, self, MASK_SHOT); + if (tr.fraction >= 1) + return false; + + // play sound + gi.sound(self, CHAN_WEAPON, gi.soundindex("weapons/push/contact.wav"), 1, ATTN_NORM, 0); + + if (tr.ent->svflags & SVF_MONSTER || + tr.ent->client) + { + // do our special form of knockback here + VectorMA (tr.ent->absmin, 0.75, tr.ent->size, v); + VectorSubtract (v, start, v); + VectorNormalize (v); + VectorMA (tr.ent->velocity, kick, v, tr.ent->velocity); + //tr.ent->velocity[2] = 48; + if (tr.ent->velocity[2] > 0) + tr.ent->groundentity = NULL; + } + else if (tr.ent->movetype == MOVETYPE_FALLFLOAT) + { + if (tr.ent->touch) + { + float mass = tr.ent->mass; + tr.ent->mass *= 0.25; + tr.ent->touch(tr.ent, self, NULL, NULL); + tr.ent->mass = mass; + } + } + + // ok, we hit something, damage it + if (!tr.ent->takedamage) + return false; + + // do the damage + T_Damage (tr.ent, self, self, aim, tr.endpos, vec3_origin, damage, kick/2, DAMAGE_NO_KNOCKBACK, MOD_HIT); + + return true; +} + +void Action_Push (edict_t *ent) +{ + if (ent->client->ps.gunframe == 0) + { + // play grunt sound + //gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/push/grunt.wav"), 1, ATTN_NORM, 0); + ent->client->ps.gunframe++; + } + else if (ent->client->ps.gunframe == 4) + { + vec3_t forward; + vec3_t offset; + vec3_t start; + + // contact + AngleVectors(ent->client->v_angle, forward, NULL, NULL); + VectorSet(offset, 0, 0, ent->viewheight * 0.5); + VectorAdd(ent->s.origin, offset, start); + push_hit(ent, start, forward, 2, 512); + ent->client->ps.gunframe++; + } + else if (ent->client->ps.gunframe == 8) + { + // go back to old weapon + ent->client->newweapon = ent->client->pers.lastweapon; + ChangeWeapon(ent); + } + else + ent->client->ps.gunframe++; +} +#endif \ No newline at end of file diff --git a/qcommon/cmd.c b/qcommon/cmd.c index b404fb9..7829b5a 100644 --- a/qcommon/cmd.c +++ b/qcommon/cmd.c @@ -328,6 +328,15 @@ qboolean Cbuf_AddLateCommands (void) Q_strncatz (text, " ", s+1); } + // start quake2:// support + // R1ch: awful hack to prevent arbitrary cmd execution with quake2:// links due to Q2's bad quote parser + if (!strncmp (text, "+connect \"quake2://", 19)) + { + if (strchr (text + 1, '+')) + Com_Error (ERR_FATAL, "Attempt to use multiple commands in a quake2:// protocol handler:\n\n%s", text); + } + // end quake2:// support + // pull out the commands build = Z_Malloc (s+1); build[0] = 0; diff --git a/qcommon/files.c b/qcommon/files.c index 5f91bf3..458c09d 100644 --- a/qcommon/files.c +++ b/qcommon/files.c @@ -827,13 +827,18 @@ bypassing the pak system. */ int FS_FOpenCompressedFile (const char *zipName, const char *fileName, fileHandle_t *f, fsMode_t mode) { - fsHandle_t *handle; + fsHandle_t *handle = NULL; char name[MAX_OSPATH]; int size; Com_sprintf (name, sizeof(name), "%s/%s", zipName, fileName); handle = FS_HandleForFile(name, f); + if (!handle) { // case of no handles available + *f = 0; + return -1; + } + Q_strncpyz(handle->name, name, sizeof(handle->name)); handle->mode = mode; diff --git a/win32/sys_console.c b/win32/sys_console.c index df9ddfc..a623ea3 100644 --- a/win32/sys_console.c +++ b/win32/sys_console.c @@ -24,6 +24,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "resource.h" #include "winquake.h" +// defines for MSVC6 +#if (_MSC_VER < 1300) +#ifndef LONG_PTR +#define LONG_PTR LONG +#endif + +#ifndef SetWindowLongPtr +#define SetWindowLongPtr SetWindowLong +#endif + +#ifndef GWLP_WNDPROC +#define GWLP_WNDPROC GWL_WNDPROC +#endif +#endif // _MSC_VER + #ifdef NEW_DED_CONSOLE @@ -88,7 +103,7 @@ char *Sys_ConsoleInput (void) if (!sys_console.cmdBuffer[0]) return NULL; - strncpy(buffer, sys_console.cmdBuffer, sizeof(buffer)); + strncpy(buffer, sys_console.cmdBuffer, sizeof(buffer)-1); sys_console.cmdBuffer[0] = 0; return buffer; @@ -164,7 +179,6 @@ void Sys_Error (char *error, ...) Qcommon_Shutdown(); va_start(argPtr, error); -// vsprintf(string, error, argPtr); Q_vsnprintf (string, sizeof(string), error, argPtr); va_end(argPtr); @@ -362,27 +376,37 @@ Sys_ShutdownConsole */ void Sys_ShutdownConsole (void) { - if (sys_console.timerActive) + if (sys_console.timerActive) { KillTimer(sys_console.hWnd, 1); + } - if (sys_console.hLogoImage) + if (sys_console.hLogoImage) { DeleteObject(sys_console.hLogoImage); - if (sys_console.hBrushMsg) + } + if (sys_console.hBrushMsg) { DeleteObject(sys_console.hBrushMsg); - if (sys_console.hBrushOutput) + } + if (sys_console.hBrushOutput) { DeleteObject(sys_console.hBrushOutput); - if (sys_console.hBrushInput) + } + if (sys_console.hBrushInput) { DeleteObject(sys_console.hBrushInput); - - if (sys_console.hFont) + } + if (sys_console.hFont) { DeleteObject(sys_console.hFont); - if (sys_console.hFontBold) + } + if (sys_console.hFontBold) { DeleteObject(sys_console.hFontBold); + } - if (sys_console.defOutputProc) - SetWindowLong(sys_console.hWndOutput, GWL_WNDPROC, (LONG)sys_console.defOutputProc); - if (sys_console.defInputProc) - SetWindowLong(sys_console.hWndInput, GWL_WNDPROC, (LONG)sys_console.defInputProc); + if (sys_console.defOutputProc) { + // SetWindowLong(sys_console.hWndOutput, GWL_WNDPROC, (LONG)sys_console.defOutputProc); + SetWindowLongPtr(sys_console.hWndOutput, GWLP_WNDPROC, (LONG_PTR)sys_console.defOutputProc); + } + if (sys_console.defInputProc) { + // SetWindowLong(sys_console.hWndInput, GWL_WNDPROC, (LONG)sys_console.defInputProc); + SetWindowLongPtr(sys_console.hWndInput, GWLP_WNDPROC, (LONG_PTR)sys_console.defInputProc); + } ShowWindow(sys_console.hWnd, SW_HIDE); DestroyWindow(sys_console.hWnd); @@ -477,8 +501,10 @@ void Sys_InitDedConsole (void) sys_console.hBrushInput = CreateSolidBrush(RGB(255, 255, 255)); // Subclass edit boxes - sys_console.defOutputProc = (WNDPROC)SetWindowLong(sys_console.hWndOutput, GWL_WNDPROC, (LONG)Sys_ConsoleEditProc); - sys_console.defInputProc = (WNDPROC)SetWindowLong(sys_console.hWndInput, GWL_WNDPROC, (LONG)Sys_ConsoleEditProc); +// sys_console.defOutputProc = (WNDPROC)SetWindowLong(sys_console.hWndOutput, GWL_WNDPROC, (LONG)Sys_ConsoleEditProc); +// sys_console.defInputProc = (WNDPROC)SetWindowLong(sys_console.hWndInput, GWL_WNDPROC, (LONG)Sys_ConsoleEditProc); + sys_console.defOutputProc = (WNDPROC)SetWindowLongPtr(sys_console.hWndOutput, GWLP_WNDPROC, (LONG_PTR)Sys_ConsoleEditProc); + sys_console.defInputProc = (WNDPROC)SetWindowLongPtr(sys_console.hWndInput, GWLP_WNDPROC, (LONG_PTR)Sys_ConsoleEditProc); // Set text limit for input edit box SendMessage(sys_console.hWndInput, EM_SETLIMITTEXT, (WPARAM)(MAX_INPUT-1), 0);