X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fcommon%2Fweapons%2Fweapon%2Fporto.qc;h=0e482d8ae82db239dbdd14160070da41befea332;hp=f5a19b2c776e98f78748d9e6d2748273929a0215;hb=e0012447bfce1b551df3dc01b043655aa93dafad;hpb=acddeee8ad8acd0099fdd25d5049e302d6246f24 diff --git a/qcsrc/common/weapons/weapon/porto.qc b/qcsrc/common/weapons/weapon/porto.qc index f5a19b2c7..0e482d8ae 100644 --- a/qcsrc/common/weapons/weapon/porto.qc +++ b/qcsrc/common/weapons/weapon/porto.qc @@ -1,53 +1,87 @@ #include "porto.qh" -#ifndef IMPLEMENTATION -CLASS(PortoLaunch, Weapon) -/* ammotype */ ATTRIB(PortoLaunch, ammo_field, .int, ammo_none); -/* impulse */ ATTRIB(PortoLaunch, impulse, int, 0); -/* flags */ ATTRIB(PortoLaunch, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_SUPERWEAPON | WEP_FLAG_NODUAL); -/* rating */ ATTRIB(PortoLaunch, bot_pickupbasevalue, float, 0); -/* color */ ATTRIB(PortoLaunch, wpcolor, vector, '0.5 0.5 0.5'); -/* modelname */ ATTRIB(PortoLaunch, mdl, string, "porto"); -#ifdef GAMEQC -/* model */ ATTRIB(PortoLaunch, m_model, Model, MDL_PORTO_ITEM); -#endif -/* crosshair */ ATTRIB(PortoLaunch, w_crosshair, string, "gfx/crosshairporto"); -/* crosshair */ ATTRIB(PortoLaunch, w_crosshair_size, float, 0.6); -/* wepimg */ ATTRIB(PortoLaunch, model2, string, "weaponporto"); -/* refname */ ATTRIB(PortoLaunch, netname, string, "porto"); -/* wepname */ ATTRIB(PortoLaunch, m_name, string, _("Port-O-Launch")); - -#define X(BEGIN, P, END, class, prefix) \ - BEGIN(class) \ - P(class, prefix, animtime, float, BOTH) \ - P(class, prefix, lifetime, float, BOTH) \ - P(class, prefix, refire, float, BOTH) \ - P(class, prefix, secondary, float, NONE) \ - P(class, prefix, speed, float, BOTH) \ - P(class, prefix, switchdelay_drop, float, NONE) \ - P(class, prefix, switchdelay_raise, float, NONE) \ - P(class, prefix, weaponreplace, string,NONE) \ - P(class, prefix, weaponstartoverride, float, NONE) \ - P(class, prefix, weaponstart, float, NONE) \ - P(class, prefix, weaponthrowable, float, NONE) \ - END() - W_PROPS(X, PortoLaunch, porto) -#undef X -ENDCLASS(PortoLaunch) -REGISTER_WEAPON(PORTO, porto, NEW(PortoLaunch)); -#ifdef SVQC -.entity porto_current; -.vector porto_v_angle; // holds "held" view angles -.float porto_v_angle_held; -.vector right_vector; -.float porto_forbidden; -#endif +#ifdef CSQC +STATIC_INIT(Porto) +{ + entity e = new_pure(porto); + e.draw = Porto_Draw; + IL_PUSH(g_drawables, e); + e.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP; +} + +const int polyline_length = 16; +.vector polyline[polyline_length]; +void Porto_Draw(entity this) +{ + if (spectatee_status || intermission == 1 || intermission == 2 || STAT(HEALTH) <= 0 || WEP_CVAR(porto, secondary)) return; + + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + entity wepent = viewmodels[slot]; + + if (wepent.activeweapon != WEP_PORTO) continue; + + vector pos = view_origin; + vector dir = view_forward; + makevectors(((autocvar_chase_active) ? warpzone_save_view_angles : view_angles)); + pos += v_right * -wepent.movedir.y + + v_up * wepent.movedir.z; + + if (wepent.angles_held_status) + { + makevectors(wepent.angles_held); + dir = v_forward; + } + + wepent.polyline[0] = pos; + + int portal_number = 0, portal1_idx = 1, portal_max = 2; + int n = 1 + 2; // 2 lines == 3 points + for (int idx = 0; idx < n && idx < polyline_length - 1; ) + { + traceline(pos, pos + 65536 * dir, true, this); + dir = reflect(dir, trace_plane_normal); + pos = trace_endpos; + wepent.polyline[++idx] = pos; + if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP) + { + n += 1; + continue; + } + if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) + { + n = max(2, idx); + break; + } + // check size + { + vector ang = vectoangles2(trace_plane_normal, dir); + ang.x = -ang.x; + makevectors(ang); + if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward)) + { + n = max(2, idx); + break; + } + } + portal_number += 1; + if (portal_number >= portal_max) break; + if (portal_number == 1) portal1_idx = idx; + } + for (int idx = 0; idx < n - 1; ++idx) + { + vector p = wepent.polyline[idx], q = wepent.polyline[idx + 1]; + if (idx == 0) p -= view_up * 16; // line from player + vector rgb = (idx < portal1_idx) ? '1 0 0' : '0 0 1'; + Draw_CylindricLine(p, q, 4, "", 1, 0, rgb, 0.5, DRAWFLAG_NORMAL, view_origin); + } + } +} #endif -#ifdef IMPLEMENTATION -#ifdef SVQC -#include -spawnfunc(weapon_porto) { weapon_defaultspawnfunc(this, WEP_PORTO); } +#ifdef SVQC +#include +#include REGISTER_MUTATOR(porto_ticker, true); MUTATOR_HOOKFUNCTION(porto_ticker, SV_StartFrame) { @@ -66,7 +100,6 @@ void W_Porto_Success(entity this) delete(this); } -string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo, .entity weaponentity); void W_Porto_Fail(entity this, float failhard) { if(this.realowner == NULL) @@ -83,7 +116,7 @@ void W_Porto_Fail(entity this, float failhard) this.realowner.porto_current = NULL; - if(this.cnt < 0 && !failhard && this.realowner.playerid == this.playerid && !IS_DEAD(this.realowner) && !(this.realowner.weapons & WEPSET(PORTO))) + if(this.cnt < 0 && !failhard && this.realowner.playerid == this.playerid && !IS_DEAD(this.realowner) && !(STAT(WEAPONS, this.realowner) & WEPSET(PORTO))) { setsize(this, '-16 -16 0', '16 16 32'); setorigin(this, this.origin + trace_plane_normal); @@ -91,7 +124,7 @@ void W_Porto_Fail(entity this, float failhard) { this.flags = FL_ITEM; IL_PUSH(g_items, this); - this.velocity = trigger_push_calculatevelocity(this.origin, this.realowner, 128); + this.velocity = trigger_push_calculatevelocity(this.origin, this.realowner, 128, this); tracetoss(this, this); if(vdist(trace_endpos - this.realowner.origin, <, 128)) { @@ -244,11 +277,11 @@ void W_Porto_Touch(entity this, entity toucher) } } -void W_Porto_Attack(entity actor, .entity weaponentity, float type) +void W_Porto_Attack(Weapon thiswep, entity actor, .entity weaponentity, float type) { entity gren; - W_SetupShot(actor, weaponentity, false, 4, SND_PORTO_FIRE, CH_WEAPON_A, 0); + W_SetupShot(actor, weaponentity, false, 4, SND_PORTO_FIRE, CH_WEAPON_A, 0, thiswep.m_id); // TODO: does the deathtype even need to be set here? porto can't hurt people // always shoot from the eye w_shotdir = v_forward; w_shotorg = actor.origin + actor.view_ofs + ((w_shotorg - actor.origin - actor.view_ofs) * v_forward) * v_forward; @@ -316,7 +349,7 @@ METHOD(PortoLaunch, wr_think, void(entity thiswep, entity actor, .entity weapone if(!actor.porto_forbidden) if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(porto, refire))) { - W_Porto_Attack(actor, weaponentity, 0); + W_Porto_Attack(thiswep, actor, weaponentity, 0); weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready); } @@ -325,7 +358,7 @@ METHOD(PortoLaunch, wr_think, void(entity thiswep, entity actor, .entity weapone if(!actor.porto_forbidden) if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(porto, refire))) { - W_Porto_Attack(actor, weaponentity, 1); + W_Porto_Attack(thiswep, actor, weaponentity, 1); weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(porto, animtime), w_ready); } } @@ -352,7 +385,7 @@ METHOD(PortoLaunch, wr_think, void(entity thiswep, entity actor, .entity weapone if(!actor.porto_forbidden) if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(porto, refire))) { - W_Porto_Attack(actor, weaponentity, -1); + W_Porto_Attack(thiswep, actor, weaponentity, -1); weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready); } } @@ -377,4 +410,3 @@ METHOD(PortoLaunch, wr_impacteffect, void(entity this, entity actor)) { LOG_WARN("Since when does Porto send DamageInfo?"); } #endif -#endif