void CopyBody(float keepvelocity)\r
{\r
local entity oldself;\r
- if (self.fakeprey)\r
- return;\r
if (self.effects & EF_NODRAW || self.alpha < 0)\r
return;\r
oldself = self;\r
self.lip = oldself.lip;\r
self.colormap = oldself.colormap;\r
self.colormod = oldself.colormod;\r
+ self.glowmod = oldself.glowmod;\r
self.iscreature = oldself.iscreature;\r
self.angles = oldself.angles;\r
self.avelocity = oldself.avelocity;\r
self.solid = oldself.solid;\r
self.takedamage = oldself.takedamage;\r
self.think = oldself.think;\r
+ self.scale = oldself.scale;\r
self.customizeentityforclient = oldself.customizeentityforclient;\r
self.uncustomizeentityforclient = oldself.uncustomizeentityforclient;\r
self.uncustomizeentityforclient_set = oldself.uncustomizeentityforclient_set;\r
self.anim_backright = '21 1 1';\r
self.anim_backleft = '22 1 1';\r
animparseerror = FALSE;\r
- animfilename = strcat(self.model, ".animinfo");\r
+ animfilename = strcat(self.playermodel, ".animinfo"); // only the normal player model may contain animation info\r
animfile = fopen(animfilename, FILE_READ);\r
if (animfile >= 0)\r
{\r
else\r
dprint("File ", animfilename, " not found, assuming legacy .zym model animation timings\n");\r
\r
- // the line below is disabled due to issues with the stomach model, which cannot be animated.\r
- // customizeentityforclient cannot let this part of the code know whether it's the stomach model or normal\r
- // player model we're using. Attempting to animate the stomach model causes BIG issues, and must not be allowed.\r
-\r
// reset animstate now\r
- //setanim(self, self.anim_idle, TRUE, FALSE, TRUE);\r
+ setanim(self, self.anim_idle, TRUE, FALSE, TRUE);\r
};\r
\r
void player_anim (void)\r
\r
if (!self.animstate_override)\r
{\r
- if (!(self.flags & FL_ONGROUND))\r
+ if(self.swallow_progress_pred)\r
+ setanim(self, self.anim_duckjump, TRUE, FALSE, FALSE); // looks good for predators who are swallowing\r
+ else if(self.swallow_progress_prey)\r
+ setanim(self, self.anim_die2, FALSE, FALSE, FALSE); // looks good for prey who's getting swallowed\r
+ else if(self.stat_eaten)\r
+ {\r
+ if(self.BUTTON_ATCK || self.predator.digesting)\r
+ setanim(self, self.anim_pain2, FALSE, TRUE, FALSE); // looks good for prey attacking the stomach or being digested\r
+ else\r
+ setanim(self, self.anim_jump, FALSE, TRUE, FALSE); // looks good for prey idling inside the stomach\r
+ }\r
+ else if (!(self.flags & FL_ONGROUND))\r
{\r
if (self.crouch)\r
setanim(self, self.anim_duckjump, FALSE, TRUE, self.restart_jump);\r
\r
if (self.weaponentity)\r
if (!self.weaponentity.animstate_override)\r
- setanim(self.weaponentity, self.weaponentity.anim_idle, TRUE, FALSE, FALSE);\r
+ {\r
+ if(self.swallow_progress_pred)\r
+ setanim(self.weaponentity, self.weaponentity.anim_fire2, TRUE, FALSE, FALSE); // looks good for predators who are swallowing\r
+ else if(self.swallow_progress_prey)\r
+ setanim(self.weaponentity, self.weaponentity.anim_reload, TRUE, FALSE, FALSE); // looks good for prey who's getting swallowed\r
+ else if(self.stat_eaten && self.BUTTON_ATCK)\r
+ setanim(self.weaponentity, self.weaponentity.anim_fire1, TRUE, FALSE, FALSE); // looks good for prey attacking the stomach\r
+ else\r
+ setanim(self.weaponentity, self.weaponentity.anim_idle, TRUE, FALSE, FALSE);\r
+ }\r
}\r
\r
-void SpawnThrownWeapon (vector org, float w)\r
+void SpawnThrownWeapon (vector org, float w, float doreduce)\r
{\r
- W_ThrowWeapon(randomvec() * 125 + '0 0 200', org - self.origin, FALSE);\r
+ W_ThrowWeapon(randomvec() * 125 + '0 0 200', org - self.origin, doreduce);\r
}\r
\r
void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
self.dmg_take = self.dmg_take + take;//max(take - 10, 0);\r
self.dmg_inflictor = inflictor;\r
\r
- if (self.health <= -75 && self.modelindex != 0)\r
- {\r
- // don't use any animations as a gib\r
- self.frame = 0;\r
- self.dead_frame = 0;\r
- // view just above the floor\r
- self.view_ofs = '0 0 4';\r
-\r
- Violence_GibSplash(self, 1, 1, attacker);\r
- self.modelindex = 0; // restore later\r
- self.solid = SOLID_NOT; // restore later\r
- }\r
+ PlayerGib(self, attacker);\r
}\r
\r
void ClientKill_Now_TeamChange();\r
// clear selected player display\r
ClearSelectedPlayer();\r
// throw a weapon\r
- SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, self.switchweapon);\r
+ SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, self.switchweapon, FALSE);\r
// print an obituary message\r
Obituary (attacker, inflictor, self, deathtype);\r
race_PreDie();\r
}\r
// clear waypoints\r
WaypointSprite_PlayerDead();\r
- // make the corpse upright (not tilted)\r
- self.angles_x = 0;\r
- self.angles_z = 0;\r
- // don't spin\r
- self.avelocity = '0 0 0';\r
- // view from the floor\r
- self.view_ofs = '0 0 -8';\r
- // toss the corpse\r
- self.movetype = MOVETYPE_TOSS;\r
- // shootable corpse\r
- self.solid = SOLID_CORPSE;\r
- // don't stick to the floor\r
- self.flags &~= FL_ONGROUND;\r
+\r
+ // configure these properties if the dead body is not a prey\r
+ if(!self.stat_eaten)\r
+ {\r
+ // make the corpse upright (not tilted)\r
+ self.angles_x = 0;\r
+ self.angles_z = 0;\r
+ // don't spin\r
+ self.avelocity = '0 0 0';\r
+ // view from the floor\r
+ self.view_ofs = '0 0 -8';\r
+ // toss the corpse\r
+ self.movetype = MOVETYPE_TOSS;\r
+ // shootable corpse\r
+ self.solid = SOLID_CORPSE;\r
+ // don't stick to the floor\r
+ self.flags &~= FL_ONGROUND;\r
+ }\r
+\r
// dying animation\r
self.deadflag = DEAD_DYING;\r
// when to allow respawn\r
}\r
}\r
\r
-.float dropweapon_check;\r
void UpdateSelectedPlayer()\r
{\r
entity selected;\r
selected = world;\r
selected_score = 0.95; // 18 degrees\r
\r
- if(self.predator.classname == "player")\r
+ if(self.stat_eaten)\r
{\r
if(!self.dropweapon_check)\r
if(self.predator.team != self.team) // don't disarm team mates when swallowing them\r
if(random() < cvar("g_balance_vore_swallow_dropweapon"))\r
- SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, self.switchweapon);\r
+ SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, self.switchweapon, TRUE);\r
self.dropweapon_check = TRUE;\r
}\r
else\r
LoadPlayerSounds(strcat(self.model, ".sounds"), 0);\r
}\r
\r
-.float soundtimefilter;\r
-.entity soundownerfilter;\r
-void GlobalSound(string sample, float chan, float voicetype)\r
+void GlobalSound(string sample, float chan, float voicetype, float vol)\r
{\r
float n;\r
float tauntrand;\r
+ float vol_scale, vol_prey, vol_apply;\r
+ float pitch;\r
\r
if(sample == "")\r
return;\r
else\r
sample = strcat(argv(0), ".wav"); // randomization\r
\r
+ // modified volume, used for attenuated (non-radio) voices\r
+ vol_scale = vol_prey = 1;\r
+ if(cvar("g_healthsize") && cvar("g_healthsize_soundfactor")) // amplify or reduce sound volume based on the size of the player\r
+ vol_scale *= bound(0, pow(self.scale, cvar("g_healthsize_soundfactor")), 1);\r
+ if(self.stat_eaten && cvar("g_vore_soundocclusion")) // reduce sound volume for prey, to simulate stomach culling\r
+ vol_prey *= bound(0, cvar("g_vore_soundocclusion"), 1);\r
+\r
+ // modified sound pitch, based on player scale\r
+ if(cvar("g_healthsize") && cvar("g_healthsize_pitch"))\r
+ pitch = pow(self.scale, -cvar("g_healthsize_pitch"));\r
+\r
switch(voicetype)\r
{\r
case VOICETYPE_LASTATTACKER_ONLY:\r
{\r
if(msg_entity.cvar_cl_voice_directional == 1)\r
{\r
- if(self.predator.classname == "player")\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE * bound(0, cvar("g_vore_soundocclusion"), 1), ATTN_MIN);\r
- else\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN);\r
+ vol_apply = vol;\r
+ vol_apply *= (self.predator != msg_entity.predator && self != msg_entity) ? vol_scale * vol_prey : vol_scale;\r
+ soundto(MSG_ONE, self, chan, sample, vol_apply, ATTN_MIN, pitch);\r
}\r
else\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);\r
+ soundto(MSG_ONE, self, chan, sample, vol, ATTN_NONE, pitch);\r
}\r
}\r
break;\r
{\r
if(msg_entity.cvar_cl_voice_directional == 1)\r
{\r
- if(self.predator.classname == "player")\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE * bound(0, cvar("g_vore_soundocclusion"), 1), ATTN_MIN);\r
- else\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN);\r
+ vol_apply = vol;\r
+ vol_apply *= (self.predator != msg_entity.predator && self != msg_entity) ? vol_scale * vol_prey : vol_scale;\r
+ soundto(MSG_ONE, self, chan, sample, vol_apply, ATTN_MIN, pitch);\r
}\r
else\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);\r
+ soundto(MSG_ONE, self, chan, sample, vol, ATTN_NONE, pitch);\r
}\r
msg_entity = self;\r
if(clienttype(msg_entity) == CLIENTTYPE_REAL)\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTN_NONE);\r
+ soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTN_NONE, pitch);\r
}\r
break;\r
case VOICETYPE_TEAMRADIO:\r
{\r
if(msg_entity.cvar_cl_voice_directional == 1)\r
{\r
- if(self.predator.classname == "player")\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE * bound(0, cvar("g_vore_soundocclusion"), 1), ATTN_MIN);\r
- else\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN);\r
+ vol_apply = vol;\r
+ vol_apply *= (self.predator != msg_entity.predator && self != msg_entity) ? vol_scale * vol_prey : vol_scale;\r
+ soundto(MSG_ONE, self, chan, sample, vol_apply, ATTN_MIN, pitch);\r
}\r
else\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);\r
+ soundto(MSG_ONE, self, chan, sample, vol, ATTN_NONE, pitch);\r
}\r
break;\r
case VOICETYPE_AUTOTAUNT:\r
break;\r
tauntrand = random();\r
FOR_EACH_REALCLIENT(msg_entity)\r
- {\r
- msg_entity.soundownerfilter = self;\r
if (tauntrand < msg_entity.cvar_cl_autotaunt)\r
- if not (self.taunt_soundtimefiltered && msg_entity.soundownerfilter.soundtimefilter > time)\r
{\r
if (msg_entity.cvar_cl_voice_directional >= 1)\r
{\r
- if(self.predator.classname == "player")\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE * bound(0, cvar("g_vore_soundocclusion"), 1), bound(ATTN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTN_MAX));\r
- else\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, bound(ATTN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTN_MAX));\r
+ vol_apply = vol;\r
+ vol_apply *= (self.predator != msg_entity.predator && self != msg_entity) ? vol_scale * vol_prey : vol_scale;\r
+ soundto(MSG_ONE, self, chan, sample, vol_apply, bound(ATTN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTN_MAX), pitch);\r
}\r
else\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);\r
-\r
- if(self.taunt_soundtimefiltered)\r
- msg_entity.soundownerfilter.soundtimefilter = time + msg_entity.cvar_cl_autotaunt_repeat;\r
+ soundto(MSG_ONE, self, chan, sample, vol, ATTN_NONE, pitch);\r
}\r
- }\r
break;\r
case VOICETYPE_TAUNT:\r
if(self.classname == "player")\r
{\r
if (msg_entity.cvar_cl_voice_directional >= 1)\r
{\r
- if(self.predator.classname == "player")\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE * bound(0, cvar("g_vore_soundocclusion"), 1), bound(ATTN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTN_MAX));\r
- else\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, bound(ATTN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTN_MAX));\r
+ vol_apply = vol;\r
+ vol_apply *= (self.predator != msg_entity.predator && self != msg_entity) ? vol_scale * vol_prey : vol_scale;\r
+ soundto(MSG_ONE, self, chan, sample, vol_apply, bound(ATTN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTN_MAX), pitch);\r
}\r
else\r
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);\r
+ soundto(MSG_ONE, self, chan, sample, vol, ATTN_NONE, pitch);\r
}\r
case VOICETYPE_PLAYERSOUND:\r
- if(self.predator.classname == "player")\r
- sound(self, chan, sample, VOL_BASE * bound(0, cvar("g_vore_soundocclusion"), 1), ATTN_NORM);\r
- else\r
- sound(self, chan, sample, VOL_BASE, ATTN_NORM);\r
+ FOR_EACH_REALCLIENT(msg_entity)\r
+ {\r
+ vol_apply = vol;\r
+ vol_apply *= (self.predator != msg_entity.predator && self != msg_entity) ? vol_scale * vol_prey : vol_scale;\r
+ soundto(MSG_ONE, self, chan, sample, vol_apply, ATTN_NORM, pitch);\r
+ }\r
break;\r
case VOICETYPE_GURGLE:\r
+ // since players can't be prey and predators at the same time, we don't use the prey modifier for the gurgle sound volume\r
if(self.stomach_load)\r
- sound(self, chan, sample, VOL_BASE * self.stomach_load / cvar("g_balance_vore_swallow_limit"), ATTN_NORM);\r
+ sound7(self, chan, sample, bound(0, vol_scale * (self.stomach_load / self.stomach_maxload), 1), ATTN_NORM, pitch, 0);\r
else\r
stopsound(self, chan);\r
break;\r
oldself = self;\r
self = player;\r
sample = self.samplefield;\r
- GlobalSound(sample, chan, voicetype);\r
+ GlobalSound(sample, chan, voicetype, VOL_BASEVOICE);\r
self = oldself;\r
}\r
\r