]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/g_hook.qc
Merge branch 'morosophos/packer-doors-always-open' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / g_hook.qc
index cccba42bb42128fff96050498f317875c050c360..b2b91bc02baf71cea1adf089e8236eea2a397667 100644 (file)
@@ -1,5 +1,8 @@
 #include "g_hook.qh"
 
+#include <server/defs.qh>
+#include <server/miscfunctions.qh>
+#include <common/effects/all.qh>
 #include "weapons/common.qh"
 #include "weapons/csqcprojectile.qh"
 #include "weapons/weaponsystem.qh"
@@ -18,8 +21,6 @@
 #include "../lib/warpzone/common.qh"
 #include "../lib/warpzone/server.qh"
 
-.int state;
-
 /*============================================
 
       Wazat's Xonotic Grappling Hook
@@ -69,29 +70,42 @@ And you should be done!
 
 ============================================*/
 
-.float hook_length;
-
-void RemoveGrapplingHook(entity pl)
+void RemoveGrapplingHooks(entity pl)
 {
-       if(pl.hook == NULL)
-               return;
-       delete(pl.hook);
-       pl.hook = NULL;
        if(pl.move_movetype == MOVETYPE_FLY)
                set_movetype(pl, MOVETYPE_WALK);
 
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+    {
+       .entity weaponentity = weaponentities[slot];
+       if(!pl.(weaponentity))
+               continue; // continue incase other slots exist?
+       if(pl.(weaponentity).hook)
+               delete(pl.(weaponentity).hook);
+       pl.(weaponentity).hook = NULL;
+    }
+
        //pl.disableclientprediction = false;
 }
 
+void RemoveHook(entity this)
+{
+       entity player = this.realowner;
+    .entity weaponentity = this.weaponentity_fld;
+
+    if(player.(weaponentity).hook == this)
+       player.(weaponentity).hook = NULL;
+
+    if(player.move_movetype == MOVETYPE_FLY)
+       set_movetype(player, MOVETYPE_WALK);
+    delete(this);
+}
+
 void GrapplingHookReset(entity this)
 {
-       if(this.realowner.hook == this)
-               RemoveGrapplingHook(this.owner);
-       else // in any case:
-               delete(this);
+       RemoveHook(this);
 }
 
-void GrapplingHookThink(entity this);
 void GrapplingHook_Stop(entity this)
 {
        Send_Effect(EFFECT_HOOK_IMPACT, this.origin, '0 0 0', 1);
@@ -117,18 +131,15 @@ bool GrapplingHookSend(entity this, entity to, int sf)
        if(sf & 1)
        {
                WriteByte(MSG_ENTITY, etof(this.realowner));
+               WriteByte(MSG_ENTITY, weaponslot(this.weaponentity_fld));
        }
        if(sf & 2)
        {
-               WriteCoord(MSG_ENTITY, this.hook_start.x);
-               WriteCoord(MSG_ENTITY, this.hook_start.y);
-               WriteCoord(MSG_ENTITY, this.hook_start.z);
+               WriteVector(MSG_ENTITY, this.hook_start);
        }
        if(sf & 4)
        {
-               WriteCoord(MSG_ENTITY, this.hook_end.x);
-               WriteCoord(MSG_ENTITY, this.hook_end.y);
-               WriteCoord(MSG_ENTITY, this.hook_end.z);
+               WriteVector(MSG_ENTITY, this.hook_end);
        }
        return true;
 }
@@ -139,14 +150,15 @@ void GrapplingHookThink(entity this)
 {
        float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch;
        vector dir, org, end, v0, dv, v, myorg, vs;
-       if(this.realowner.hook != this) // how did that happen?
+       .entity weaponentity = this.weaponentity_fld;
+       if(this.realowner.(weaponentity).hook != this)  // how did that happen?
        {
                error("Owner lost the hook!\n");
                return;
        }
-       if(LostMovetypeFollow(this) || gameover || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || ((this.aiment.flags & FL_PROJECTILE) && this.aiment.classname != "nade"))
+       if(LostMovetypeFollow(this) || game_stopped || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || ((this.aiment.flags & FL_PROJECTILE) && this.aiment.classname != "nade"))
        {
-               RemoveGrapplingHook(this.realowner);
+               RemoveHook(this);
                return;
        }
        if(this.aiment)
@@ -154,7 +166,7 @@ void GrapplingHookThink(entity this)
 
        this.nextthink = time;
 
-       int s = W_GetGunAlignment(this.realowner);
+       int s = W_GunAlign(this.realowner.(weaponentity), STAT(GUNALIGN, this.realowner)) - 1;
        vs = hook_shotorigin[s];
 
        makevectors(this.realowner.v_angle);
@@ -206,7 +218,7 @@ void GrapplingHookThink(entity this)
                        v = v0 = WarpZone_RefSys_TransformVelocity(pull_entity, this, pull_entity.velocity);
 
                        // first pull the rope...
-                       if(this.realowner.hook_state & HOOK_PULLING)
+                       if(this.realowner.(weaponentity).hook_state & HOOK_PULLING)
                        {
                                newlength = this.hook_length;
                                newlength = max(newlength - pullspeed * frametime, minlength);
@@ -224,7 +236,7 @@ void GrapplingHookThink(entity this)
                        if(pull_entity.move_movetype == MOVETYPE_FLY)
                                set_movetype(pull_entity, MOVETYPE_WALK);
 
-                       if(this.realowner.hook_state & HOOK_RELEASING)
+                       if(this.realowner.(weaponentity).hook_state & HOOK_RELEASING)
                        {
                                newlength = dist;
                                this.hook_length = newlength;
@@ -266,7 +278,7 @@ void GrapplingHookThink(entity this)
 
                        if(frozen_pulling && autocvar_g_balance_grapplehook_pull_frozen == 2 && !STAT(FROZEN, this.aiment))
                        {
-                               RemoveGrapplingHook(this.realowner);
+                               RemoveHook(this);
                                return;
                        }
                }
@@ -311,7 +323,7 @@ void GrapplingHookTouch(entity this, entity toucher)
        GrapplingHook_Stop(this);
 
        if(toucher)
-               if(toucher.move_movetype != MOVETYPE_NONE)
+               //if(toucher.move_movetype != MOVETYPE_NONE)
                {
                        SetMovetypeFollow(this, toucher);
                        WarpZone_RefSys_BeginAddingIncrementally(this, this.aiment);
@@ -320,17 +332,17 @@ void GrapplingHookTouch(entity this, entity toucher)
        //this.realowner.disableclientprediction = true;
 }
 
-void GrapplingHook_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+void GrapplingHook_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
 {
-       if(this.health <= 0)
+       if(GetResource(this, RES_HEALTH) <= 0)
                return;
 
        if (!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) // no exceptions
                return; // g_balance_projectiledamage says to halt
 
-       this.health = this.health - damage;
+       TakeResource(this, RES_HEALTH, damage);
 
-       if (this.health <= 0)
+       if (GetResource(this, RES_HEALTH) <= 0)
        {
                if(attacker != this.realowner)
                {
@@ -338,36 +350,23 @@ void GrapplingHook_Damage(entity this, entity inflictor, entity attacker, float
                        this.realowner.pushltime = time + autocvar_g_maxpushtime;
                        this.realowner.istypefrag = PHYS_INPUT_BUTTON_CHAT(this.realowner);
                }
-               RemoveGrapplingHook(this.realowner);
+               RemoveHook(this);
        }
 }
 
-void FireGrapplingHook(entity actor)
+void FireGrapplingHook(entity actor, .entity weaponentity)
 {
-       entity missile;
-       vector org;
-       vector vs;
-
-       if(forbidWeaponUse(actor)) return;
+       if(weaponLocked(actor)) return;
        if(actor.vehicle) return;
 
-       makevectors(actor.v_angle);
-
-       int s = W_GetGunAlignment(actor);
-       vs = hook_shotorigin[s];
-
-       // UGLY WORKAROUND: play this on CH_WEAPON_B so it can't cut off fire sounds
-       sound (actor, CH_WEAPON_B, SND_HOOK_FIRE, VOL_BASE, ATTEN_NORM);
-       org = actor.origin + actor.view_ofs + v_forward * vs.x + v_right * -vs.y + v_up * vs.z;
-
-       tracebox(actor.origin + actor.view_ofs, '-3 -3 -3', '3 3 3', org, MOVE_NORMAL, actor);
-       org = trace_endpos;
-
-       Send_Effect(EFFECT_HOOK_MUZZLEFLASH, org, '0 0 0', 1);
+       // TODO: offhand hook shoots from eye
+       W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', true, 0, SND_HOOK_FIRE, CH_WEAPON_B, 0, WEP_HOOK.m_id);
+       Send_Effect(EFFECT_HOOK_MUZZLEFLASH, w_shotorg, '0 0 0', 1);
 
-       missile = WarpZone_RefSys_SpawnSameRefSys(actor);
+       entity missile = WarpZone_RefSys_SpawnSameRefSys(actor);
        missile.owner = missile.realowner = actor;
-       actor.hook = missile;
+       actor.(weaponentity).hook = missile;
+       missile.weaponentity_fld = weaponentity;
        missile.reset = GrapplingHookReset;
        missile.classname = "grapplinghook";
        missile.flags = FL_PROJECTILE;
@@ -379,11 +378,11 @@ void FireGrapplingHook(entity actor)
 
        //setmodel (missile, MDL_HOOK); // precision set below
        setsize (missile, '-3 -3 -3', '3 3 3');
-       setorigin(missile, org);
+       setorigin(missile, w_shotorg);
 
        missile.state = 0; // not latched onto anything
 
-       W_SetupProjVelocity_Explicit(missile, v_forward, v_up, autocvar_g_balance_grapplehook_speed_fly, 0, 0, 0, false);
+       W_SetupProjVelocity_Explicit(missile, w_shotdir, v_up, autocvar_g_balance_grapplehook_speed_fly, 0, 0, 0, false);
 
        missile.angles = vectoangles (missile.velocity);
        //missile.glow_color = 250; // 244, 250
@@ -394,7 +393,7 @@ void FireGrapplingHook(entity actor)
 
        missile.effects = /*EF_FULLBRIGHT | EF_ADDITIVE |*/ EF_LOWPRECISION;
 
-       missile.health = autocvar_g_balance_grapplehook_health;//120
+       SetResourceExplicit(missile, RES_HEALTH, autocvar_g_balance_grapplehook_health);
        missile.event_damage = GrapplingHook_Damage;
        missile.takedamage = DAMAGE_AIM;
        missile.damageforcescale = 0;