+ if (v_shot_idx) // v_ model attached to invisible h_ model
+ {
+ this.movedir = gettaginfo(this.weaponchild, v_shot_idx);
+ }
+ else
+ {
+ int idx;
+ if ((idx = gettagindex(this, "shot")) || (idx = gettagindex(this, "tag_shot")))
+ {
+ this.movedir = gettaginfo(this, idx);
+ }
+ else
+ {
+ LOG_WARNINGF("weapon model %s does not support the 'shot' tag, will display shots TOTALLY wrong\n",
+ this.model);
+ this.movedir = '0 0 0';
+ }
+ }
+ {
+ int idx = 0;
+ // v_ model attached to invisible h_ model
+ if (this.weaponchild
+ && ((idx = gettagindex(this.weaponchild, "shell")) || (idx = gettagindex(this.weaponchild, "tag_shell"))))
+ {
+ this.spawnorigin = gettaginfo(this.weaponchild, idx);
+ }
+ else if ((idx = gettagindex(this, "shell")) || (idx = gettagindex(this, "tag_shell")))
+ {
+ this.spawnorigin = gettaginfo(this, idx);
+ }
+ else
+ {
+ LOG_WARNINGF("weapon model %s does not support the 'shell' tag, will display casings wrong\n",
+ this.model);
+ this.spawnorigin = this.movedir;
+ }
+ }
+ if (v_shot_idx)
+ {
+ this.oldorigin = '0 0 0'; // use regular attachment
+ }
+ else
+ {
+ int idx;
+ if (this.weaponchild)
+ (idx = gettagindex(this, "weapon")) || (idx = gettagindex(this, "tag_weapon"));
+ else
+ (idx = gettagindex(this, "handle")) || (idx = gettagindex(this, "tag_handle"));
+ if (idx)
+ {
+ this.oldorigin = this.movedir - gettaginfo(this, idx);
+ }
+ else
+ {
+ LOG_WARNINGF(
+ "weapon model %s does not support the 'handle' tag "
+ "and neither does the v_ model support the 'shot' tag, "
+ "will display muzzle flashes TOTALLY wrong\n",
+ this.model);
+ this.oldorigin = '0 0 0'; // there is no way to recover from this
+ }
+ }
+
+#ifdef SVQC
+ this.viewmodelforclient = this.owner;
+#else
+ this.renderflags |= RF_VIEWMODEL;
+#endif
+ }
+
+ this.view_ofs = '0 0 0';
+
+ if (this.movedir.x >= 0)
+ {
+ int algn = STAT(GUNALIGN, this.owner);
+ vector v = this.movedir;
+ this.movedir = shotorg_adjust(v, false, false, algn);
+ this.view_ofs = shotorg_adjust(v, false, true, algn) - v;
+ }
+ int compressed_shotorg = compressShotOrigin(this.movedir);
+ // make them match perfectly
+#ifdef SVQC
+ this.movedir = decompressShotOrigin(this.owner.stat_shotorg = compressed_shotorg);
+#else
+ this.movedir = decompressShotOrigin(compressed_shotorg);
+#endif
+
+ this.spawnorigin += this.view_ofs; // offset the casings origin by the same amount
+
+ // check if an instant weapon switch occurred
+ setorigin(this, this.view_ofs);
+ // reset animstate now
+ this.wframe = WFRAME_IDLE;
+ setanim(this, this.anim_idle, true, false, true);
+}
+#endif
+
+#ifndef MENUQC
+
+REGISTER_NET_TEMP(wframe)
+#ifdef CSQC
+NET_HANDLE(wframe, bool isNew)
+{
+ vector a;
+ a.x = ReadCoord();
+ a.y = ReadCoord();
+ a.z = ReadCoord();
+ bool restartanim = ReadByte();
+ anim_set(viewmodel, a, !restartanim, restartanim, restartanim);
+ viewmodel.state = ReadByte();
+ viewmodel.weapon_nextthink = ReadFloat();
+ viewmodel.alpha = ReadByte() / 255;
+ switch (viewmodel.state)
+ {
+ case WS_RAISE:
+ viewmodel.weapon_switchdelay = activeweapon.switchdelay_raise;
+ break;
+ case WS_DROP:
+ viewmodel.weapon_switchdelay = activeweapon.switchdelay_drop;
+ break;
+ default:
+ viewmodel.weapon_switchdelay = 0;
+ break;
+ }
+ return true;
+}
+#endif
+
+#ifdef SVQC
+void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim)
+{
+ if (!IS_REAL_CLIENT(actor)) return;
+ int channel = MSG_ONE;
+ msg_entity = actor;
+ WriteHeader(channel, wframe);
+ WriteCoord(channel, a.x);
+ WriteCoord(channel, a.y);
+ WriteCoord(channel, a.z);
+ WriteByte(channel, restartanim);
+ WriteByte(channel, weaponentity.state);
+ WriteFloat(channel, weaponentity.weapon_nextthink);
+ WriteByte(channel, weaponentity.m_alpha * 255);
+}
+#endif
+
+REGISTER_NET_C2S(w_whereis)
+#ifdef SVQC
+void Weapon_whereis(Weapon this, entity cl);
+NET_HANDLE(w_whereis, bool)
+{
+ Weapon wpn = ReadRegistered(Weapons);
+ if (wpn != WEP_Null) Weapon_whereis(wpn, sender);
+ return true;
+}
+#else
+void w_whereis(Weapon this)
+{
+ int channel = MSG_C2S;
+ WriteHeader(channel, w_whereis);
+ WriteRegistered(Weapons, channel, this);
+}
+CLIENT_COMMAND(weapon_find, "Show spawn locations of a weapon")
+{
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ string s = argv(1);
+ if (s == "all")
+ {
+ FOREACH(Weapons, it != WEP_Null, w_whereis(it));
+ return;
+ }
+ if (s == "unowned")
+ {
+ FOREACH(Weapons, it != WEP_Null && !(STAT(WEAPONS) & it.m_wepset), w_whereis(it));
+ return;
+ }
+ FOREACH(Weapons, it != WEP_Null && it.netname == s,
+ {
+ w_whereis(it);
+ return;
+ });
+ }
+ default:
+ {
+ LOG_INFOF("Incorrect parameters for ^2%s^7\n", "weapon_find");
+ }
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_INFO("\nUsage:^3 cl_cmd weapon_find weapon\n");
+ LOG_INFO(" Where 'weapon' is the lowercase weapon name, 'all' or 'unowned'.\n");
+ return;
+ }
+ }
+}
+#endif
+
+
+#endif
+