-/*
- * supported formats:
- *
- * 1. simple animated model, muzzle flash handling on h_ model:
- * h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
- * tags:
- * shot = muzzle end (shot origin, also used for muzzle flashes)
- * shell = casings ejection point (must be on the right hand side of the gun)
- * weapon = attachment for v_tuba.md3
- * v_tuba.md3 - first and third person model
- * g_tuba.md3 - pickup model
- *
- * 2. simple animated model, muzzle flash handling on v_ model:
- * h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
- * tags:
- * weapon = attachment for v_tuba.md3
- * v_tuba.md3 - first and third person model
- * tags:
- * shot = muzzle end (shot origin, also used for muzzle flashes)
- * shell = casings ejection point (must be on the right hand side of the gun)
- * g_tuba.md3 - pickup model
- *
- * 3. fully animated model, muzzle flash handling on h_ model:
- * h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
- * tags:
- * shot = muzzle end (shot origin, also used for muzzle flashes)
- * shell = casings ejection point (must be on the right hand side of the gun)
- * handle = corresponding to the origin of v_tuba.md3 (used for muzzle flashes)
- * v_tuba.md3 - third person model
- * g_tuba.md3 - pickup model
- *
- * 4. fully animated model, muzzle flash handling on v_ model:
- * h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
- * tags:
- * shot = muzzle end (shot origin)
- * shell = casings ejection point (must be on the right hand side of the gun)
- * v_tuba.md3 - third person model
- * tags:
- * shot = muzzle end (for muzzle flashes)
- * g_tuba.md3 - pickup model
- */
-
-// writes:
-// self.origin, self.angles
-// self.weaponentity
-// self.movedir, self.view_ofs
-// attachment stuff
-// anim stuff
-// to free:
-// call again with ""
-// remove the ent
-void CL_WeaponEntity_SetModel(string name)
-{SELFPARAM();
- float v_shot_idx;
- if (name != "")
- {
- // if there is a child entity, hide it until we're sure we use it
- if (self.weaponentity)
- self.weaponentity.model = "";
- _setmodel(self, W_Model(strcat("v_", name, ".md3")));
- v_shot_idx = gettagindex(self, "shot"); // used later
- if(!v_shot_idx)
- v_shot_idx = gettagindex(self, "tag_shot");
-
- _setmodel(self, W_Model(strcat("h_", name, ".iqm")));
- // preset some defaults that work great for renamed zym files (which don't need an animinfo)
- self.anim_fire1 = animfixfps(self, '0 1 0.01', '0 0 0');
- self.anim_fire2 = animfixfps(self, '1 1 0.01', '0 0 0');
- self.anim_idle = animfixfps(self, '2 1 0.01', '0 0 0');
- self.anim_reload = animfixfps(self, '3 1 0.01', '0 0 0');
-
- // if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model)
- // if we don't, this is a "real" animated model
- if(gettagindex(self, "weapon"))
- {
- if (!self.weaponentity)
- self.weaponentity = spawn();
- _setmodel(self.weaponentity, W_Model(strcat("v_", name, ".md3")));
- setattachment(self.weaponentity, self, "weapon");
- }
- else if(gettagindex(self, "tag_weapon"))
- {
- if (!self.weaponentity)
- self.weaponentity = spawn();
- _setmodel(self.weaponentity, W_Model(strcat("v_", name, ".md3")));
- setattachment(self.weaponentity, self, "tag_weapon");
- }
- else
- {
- if(self.weaponentity)
- remove(self.weaponentity);
- self.weaponentity = world;
- }
-
- setorigin(self,'0 0 0');
- self.angles = '0 0 0';
- self.frame = 0;
- self.viewmodelforclient = world;
-
- float idx;
-
- if(v_shot_idx) // v_ model attached to invisible h_ model
- {
- self.movedir = gettaginfo(self.weaponentity, v_shot_idx);
- }
- else
- {
- idx = gettagindex(self, "shot");
- if(!idx)
- idx = gettagindex(self, "tag_shot");
- if(idx)
- self.movedir = gettaginfo(self, idx);
- else
- {
- LOG_INFO("WARNING: weapon model ", self.model, " does not support the 'shot' tag, will display shots TOTALLY wrong\n");
- self.movedir = '0 0 0';
- }
- }
-
- if(self.weaponentity) // v_ model attached to invisible h_ model
- {
- idx = gettagindex(self.weaponentity, "shell");
- if(!idx)
- idx = gettagindex(self.weaponentity, "tag_shell");
- if(idx)
- self.spawnorigin = gettaginfo(self.weaponentity, idx);
- }
- else
- idx = 0;
- if(!idx)
- {
- idx = gettagindex(self, "shell");
- if(!idx)
- idx = gettagindex(self, "tag_shell");
- if(idx)
- self.spawnorigin = gettaginfo(self, idx);
- else
- {
- LOG_INFO("WARNING: weapon model ", self.model, " does not support the 'shell' tag, will display casings wrong\n");
- self.spawnorigin = self.movedir;
- }
- }
-
- if(v_shot_idx)
- {
- self.oldorigin = '0 0 0'; // use regular attachment
- }
- else
- {
- if(self.weaponentity)
- {
- idx = gettagindex(self, "weapon");
- if(!idx)
- idx = gettagindex(self, "tag_weapon");
- }
- else
- {
- idx = gettagindex(self, "handle");
- if(!idx)
- idx = gettagindex(self, "tag_handle");
- }
- if(idx)
- {
- self.oldorigin = self.movedir - gettaginfo(self, idx);
- }
- else
- {
- LOG_INFO("WARNING: weapon model ", self.model, " does not support the 'handle' tag and neither does the v_ model support the 'shot' tag, will display muzzle flashes TOTALLY wrong\n");
- self.oldorigin = '0 0 0'; // there is no way to recover from this
- }
- }
-
- self.viewmodelforclient = self.owner;
- }
- else
- {
- self.model = "";
- if(self.weaponentity)
- remove(self.weaponentity);
- self.weaponentity = world;
- self.movedir = '0 0 0';
- self.spawnorigin = '0 0 0';
- self.oldorigin = '0 0 0';
- self.anim_fire1 = '0 1 0.01';
- self.anim_fire2 = '0 1 0.01';
- self.anim_idle = '0 1 0.01';
- self.anim_reload = '0 1 0.01';
- }
-
- self.view_ofs = '0 0 0';
-
- if(self.movedir.x >= 0)
- {
- vector v0;
- v0 = self.movedir;
- self.movedir = shotorg_adjust(v0, false, false, self.owner.cvar_cl_gunalign);
- self.view_ofs = shotorg_adjust(v0, false, true, self.owner.cvar_cl_gunalign) - v0;
- }
- self.owner.stat_shotorg = compressShotOrigin(self.movedir);
- self.movedir = decompressShotOrigin(self.owner.stat_shotorg); // make them match perfectly
-
- self.spawnorigin += self.view_ofs; // offset the casings origin by the same amount
-
- // check if an instant weapon switch occurred
- setorigin(self, self.view_ofs);
- // reset animstate now
- self.wframe = WFRAME_IDLE;
- setanim(self, self.anim_idle, true, false, true);
-}
-
-vector CL_Weapon_GetShotOrg(float wpn)
-{SELFPARAM();
- entity wi = get_weaponinfo(wpn);
- setself(spawn());
- CL_WeaponEntity_SetModel(wi.mdl);
- vector ret = self.movedir;
- CL_WeaponEntity_SetModel("");
- remove(self);
- setself(this);