nuclide/Source/client/player.c

305 lines
7.7 KiB
C

/***
*
* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved.
*
* See the file LICENSE attached with the sources for usage details.
*
****/
//.float bonecontrol1; //Half-Life model format bone controller. On player models, this typically affects the spine's yaw.
//.float bonecontrol2; //Half-Life model format bone controller. On player models, this typically affects the spine's yaw.
//.float bonecontrol3; //Half-Life model format bone controller. On player models, this typically affects the spine's yaw.
//.float bonecontrol4; //Half-Life model format bone controller. On player models, this typically affects the spine's yaw.
//.float bonecontrol5; //Half-Life model format bone controller. This typically affects the mouth.
//.float subblendfrac; //Weird animation value specific to Half-Life models. On player models, this typically affects the spine's pitch.
//.float basesubblendfrac; // legs part.
.float subblend2frac; // Up/Down
// TODO: This needs to be redone.
#ifdef CSTRIKE
string sPModels[CS_WEAPON_COUNT - 1] = {
"models/p_knife.mdl",
"models/p_usp.mdl",
"models/p_glock18.mdl",
"models/p_deagle.mdl",
"models/p_p228.mdl",
"models/p_elite.mdl",
"models/p_fiveseven.mdl",
"models/p_m3.mdl",
"models/p_xm1014.mdl",
"models/p_mp5.mdl",
"models/p_p90.mdl",
"models/p_ump45.mdl",
"models/p_mac10.mdl",
"models/p_tmp.mdl",
"models/p_ak47.mdl",
"models/p_sg552.mdl",
"models/p_m4a1.mdl",
"models/p_aug.mdl",
"models/p_scout.mdl",
"models/p_awp.mdl",
"models/p_g3sg1.mdl",
"models/p_sg550.mdl",
"models/p_m249.mdl",
"models/p_c4.mdl",
"models/p_flashbang.mdl",
"models/p_hegrenade.mdl",
"models/p_smokegrenade.mdl"
};
#endif
void player::gun_offset(void)
{
vector v1, v2;
#ifdef VALVE
if (playertype == PLAYERTYPE_Q2) {
p_model.scale = 1.4;
if (flags & FL_CROUCHING) {
setorigin(p_model, origin + [0,0, 16]);
} else {
setorigin(p_model, origin + [0,0, -2]);
}
p_model.angles = this.angles;
p_model.frame = frame;
p_model.frame2 = frame2;
p_model.lerpfrac = lerpfrac;
return;
}
#endif
/* Set it to something consistent */
this.p_model.angles = this.angles;
/* Updates the v_ globals for the player hand bone angle */
gettaginfo(this, this.p_hand_bone);
/* Create angles from the v_ matrix */
v1 = vectoangles(v_right, v_up);
/* Updates the v_ globals for the weapon hand bone angle */
gettaginfo(this.p_model, this.p_model_bone);
v2 = vectoangles(v_right, v_up);
/* The difference is applied */
this.p_model.angles = this.angles + (v1 - v2);
/* Fix the origin */
setorigin(this.p_model, this.origin);
vector ofs = gettaginfo(this.p_model, this.p_model_bone) - gettaginfo(this, this.p_hand_bone);
setorigin(this.p_model, this.origin - ofs);
}
#ifdef VALVE
string Weapons_GetPlayermodel(int);
#endif
void player::draw(void)
{
if (!this.p_model) {
this.p_model = spawn();
this.p_model.classname = "pmodel";
this.p_model.owner = this;
}
this.subblendfrac =
this.subblend2frac = this.pitch / 90;
#warning "FIXME: This ifdef needs to go in the future"
#ifdef VALVE
if (playertype == PLAYERTYPE_HL) {
/* Only bother updating the model if the weapon has changed */
if (this.lastweapon != this.activeweapon) {
if (this.activeweapon) {
#ifdef CSTRIKE
setmodel(this.p_model, sPModels[this.activeweapon - 1]);
#else
setmodel(this. p_model, Weapons_GetPlayermodel(this.activeweapon));
#endif
} else {
setmodel(this.p_model, "");
}
this.lastweapon = this.activeweapon;
/* Update the bone index of the current p_ model so we can calculate the offset
* and get the weapon bone ID for the current player model */
this.p_hand_bone = gettagindex(this, "Bip01 R Hand");
this.p_model_bone = gettagindex(this.p_model, "Bip01 R Hand");
}
Animation_PlayerUpdate();
} else {
if (!this.p_model.modelindex) {
tokenizebyseparator(getplayerkeyvalue(entnum-1, "model"), "/");
setmodel(this.p_model, sprintf("players/%s/weapon.md2", argv(0)));
}
Animation_Q2PlayerUpdate();
return;
}
#else
Animation_PlayerUpdate();
#endif
/*makevectors([0, this.angles[1], 0]);
float fDirection = dotproduct(this.velocity, v_forward);
if (fDirection != 0)
print(sprintf("fDirection: %d\n", fDirection));
if (fDirection < 0) {
this.baseframe1time -= clframetime;
this.baseframe2time -= clframetime;
this.frame2time -= clframetime;
this.frame1time -= clframetime;
} else {*/
this.baseframe1time += clframetime;
this.baseframe2time += clframetime;
this.frame2time += clframetime;
this.frame1time += clframetime;
/*}*/
this.bonecontrol5 = getplayerkeyfloat(this.entnum - 1, "voiploudness");
makevectors([0, this.angles[1], 0]);
float fCorrect = dotproduct(this.velocity, v_right);
float a, s;
if (this.velocity[0] == 0 && this.velocity[1] == 0) {
a = 0;
s = 0;
} else {
a = this.angles[1] - vectoyaw(this.velocity);
s = vlen(this.velocity);
if (s < 100) {
a *= s/100;
}
}
s /= 400;
/* Clamp */
if (a < -180) {
a += 360;
}
if (a > 180) {
a -= 360;
}
if (a > 120) {
a = 120;
}
if (a < -120) {
a = -120;
}
/* Turn torso */
this.bonecontrol2 = (a)/-120;
/* Correct the legs */
this.angles[1] -= a;
}
var float autocvar_standheight = 0;
var float autocvar_crouchheight = 0;
float player::predraw(void)
{
/* Handle the flashlights... */
if (flags & FL_FLASHLIGHT) {
vector src;
vector ang;
if (this.entnum != player_localentnum) {
src = origin + view_ofs;
ang = [pitch, angles[1], angles[2]];
} else {
src = getproperty(VF_ORIGIN);
ang = getproperty(VF_CL_VIEWANGLES);
}
makevectors(ang);
traceline(src, src + (v_forward * 8096), FALSE, self);
if (serverkeyfloat("*bspversion") == 30) {
dynamiclight_add(trace_endpos + (v_forward * -2), 128, [1,1,1]);
} else {
float p = dynamiclight_add(src, 512, [1,1,1], 0, "textures/flashlight");
dynamiclight_set(p, LFIELD_ANGLES, ang);
}
}
/* Run animations regardless of rendering the player */
draw();
gun_offset();
#ifdef VALVE
/* Size of appearance and bounding box is different from game to game */
if (playertype == PLAYERTYPE_Q2) {
scale = 1.4;
if (flags & FL_CROUCHING) {
setorigin(this, this.origin + [0,0, 16]);
} else {
setorigin(this, this.origin + [0,0, -2]);
}
}
#endif
if (autocvar_cl_thirdperson == TRUE || this.entnum != player_localentnum) {
Voice_Draw3D(this);
addentity(this);
addentity(this.p_model);
} else {
removeentity(this);
removeentity(this.p_model);
}
return PREDRAW_NEXT;
}
void player::postdraw(void)
{
#ifdef VALVE
/* Correct offsets */
if (playertype == PLAYERTYPE_Q2) {
if (flags & FL_CROUCHING) {
setorigin(this, this.origin - [0,0, 16]);
} else {
setorigin(this, this.origin - [0,0, -2]);
}
scale = 1.0;
}
#endif
}
void player::set_model(string mpath)
{
#ifdef VALVE
string modelout;
string skinpath = "";
string skinout = "";
int i;
i = tokenizebyseparator(mpath, "/");
if (i == 1) {
playertype = PLAYERTYPE_HL;
modelout = sprintf("models/player/%s/%s.mdl", argv(0), argv(0));
} else {
playertype = PLAYERTYPE_Q2;
modelout = sprintf("players/%s/tris.md2", argv(0));
skinout = sprintf("players/%s/%s.pcx", argv(0), argv(1));
skinpath = sprintf("players/%s/%s.skin", argv(0), argv(1));
/* If the skin doesn't exist, make sure we fail */
if (whichpack(skinout)) {
} else {
print( sprintf( "Skin %s does not exist.\n", skinout ) );
skinpath = __NULL__;
skinout = __NULL__;
modelout = __NULL__;
}
}
if (modelout && whichpack(modelout)) {
setmodel(this, modelout);
if (playertype == PLAYERTYPE_Q2) {
setcustomskin(this, skinpath, sprintf("replace \"\" \"%s\"", skinout));
}
} else {
modelout = "models/player.mdl";
setmodel(this, modelout);
playertype = PLAYERTYPE_HL;
}
#endif
}