1 void() grapple_ready_01;
\r
2 void() grapple_fire1_01;
\r
3 void() grapple_deselect_01;
\r
4 void() grapple_select_01;
\r
6 float() grapple_check =
\r
11 void(float req) w_grapple =
\r
15 else if (req == WR_FIRE1)
\r
16 weapon_prepareattack(grapple_check, grapple_check, grapple_fire1_01, cvar("g_balance_grapple_refire"));
\r
17 else if (req == WR_RAISE)
\r
18 grapple_select_01();
\r
19 else if (req == WR_UPDATECOUNTS)
\r
20 self.currentammo = 1;
\r
21 else if (req == WR_DROP)
\r
22 grapple_deselect_01();
\r
23 else if (req == WR_SETUP)
\r
24 weapon_setup(WEP_GRAPPLE, "w_grapple.zym", 0);
\r
25 else if (req == WR_CHECKAMMO)
\r
26 weapon_hasammo = grapple_check();
\r
29 void RemoveGrapplingHook(entity pl)
\r
31 if(pl.hook == world)
\r
35 if(pl.movetype == MOVETYPE_FLY)
\r
36 pl.movetype = MOVETYPE_WALK;
\r
39 void GrapplingHookThink()
\r
41 float spd, dist, minlength, pullspeed, pullspeed2, totalmass, m1, m2, dropspd1, dropspd2;
\r
42 vector dir, org, end;
\r
44 makevectors(self.owner.v_angle);
\r
45 org = self.owner.origin + self.owner.view_ofs + v_forward * 15 - v_right * 5 + v_up * -12;
\r
47 traceline(self.origin, org, TRUE, self);
\r
48 if(self.owner.health <= 2 // owner died
\r
49 || self.owner.hook != self // owner fired a different hook
\r
50 || !self.owner.button0 // owner let go of button
\r
51 || trace_fraction < 1) // owner not visible
\r
57 self.nextthink = time + 0.1;
\r
58 dropspd1 = cvar("sv_gravity") * 0.1; // thinks this often
\r
59 dropspd2 = dropspd1;
\r
60 if(self.owner.gravity)
\r
61 dropspd1 = dropspd1 * self.owner.gravity;
\r
62 if(self.enemy.gravity)
\r
63 dropspd2 = dropspd2 * self.enemy.gravity;
\r
64 self.owner.attack_finished = max(self.owner.attack_finished, time + cvar("g_balance_grapple_refire"));
\r
68 self.owner.jump_pad = 1;
\r
73 pullspeed = cvar("g_balance_grapple_pullspeed");
\r
74 if(self.enemy != world) // pull both players toward each other at different speeds based on mass
\r
76 m1 = self.owner.mass;
\r
77 m2 = self.enemy.mass;
\r
82 totalmass = m1 + m2;
\r
83 pullspeed2 = (m1 / totalmass) * pullspeed;
\r
84 pullspeed = (m2 / totalmass) * pullspeed;
\r
87 dir = self.origin - org;
\r
89 dir = normalize(dir);
\r
91 end = self.origin - dir*minlength;
\r
93 dist = vlen(end - org);
\r
95 if(dist < 200 && self.enemy == world)
\r
96 spd = dist * (pullspeed / 200);
\r
102 if(!(dist < 200 && !self.owner.flags & FL_ONGROUND && self.enemy != world))
\r
103 self.owner.velocity = dir*spd;
\r
104 self.owner.movetype = MOVETYPE_FLY;
\r
105 self.owner.flags = self.owner.flags - (self.owner.flags & FL_ONGROUND);
\r
107 org = org + dir*50; // get the beam out of the player's eyes
\r
109 if(self.enemy != world)
\r
111 self.origin = 0.5*(self.enemy.absmin+self.enemy.absmax) + '0 0 10'; // follow enemy's body
\r
114 spd = dist * (pullspeed2 / 200 + 150);
\r
121 if(dist < 200 && !self.owner.flags & FL_ONGROUND)
\r
123 //self.enemy.velocity = self.enemy.velocity + '0 0 -1'*dropspd1;
\r
124 self.owner.velocity = self.owner.velocity + '0 0 -1'*dropspd2; // fake effects of gravity, and don't pull enemy toward me
\r
127 self.enemy.velocity = dir * spd * -1;
\r
129 if(self.attack_finished < time)
\r
131 self.attack_finished = time + cvar("g_balance_grapple_hurtrate");
\r
132 Damage (self.enemy, self, self.owner, cvar("g_balance_grapple_damage2"), WEP_GRAPPLE, self.origin, '0 0 0');
\r
134 if(self.enemy.health <= 0) // gib the dead player
\r
136 Damage (self.enemy, self, self.owner, 100, WEP_GRAPPLE, self.origin, '0 0 0');
\r
137 self.enemy = world;
\r
138 self.owner.hook = world;
\r
145 WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
\r
146 WriteByte (MSG_BROADCAST, TE_BEAM);
\r
147 WriteEntity (MSG_BROADCAST, self);
\r
148 WriteCoord (MSG_BROADCAST, self.origin_x);
\r
149 WriteCoord (MSG_BROADCAST, self.origin_y);
\r
150 WriteCoord (MSG_BROADCAST, self.origin_z);
\r
151 WriteCoord (MSG_BROADCAST, org_x);
\r
152 WriteCoord (MSG_BROADCAST, org_y);
\r
153 WriteCoord (MSG_BROADCAST, org_z);
\r
154 //WriteCoord (MSG_BROADCAST, 0);
\r
155 //WriteCoord (MSG_BROADCAST, 0);
\r
156 //WriteCoord (MSG_BROADCAST, 0);
\r
159 void GrapplingHookTouch (void)
\r
161 if (other == self.owner)
\r
163 else if (pointcontents (self.origin) == CONTENT_SKY)
\r
165 RemoveGrapplingHook(self.owner);
\r
169 self.event_damage = SUB_Null; // fixme: ability to dislodge a player by damaging hook?
\r
170 sound (self, CHAN_BODY, "weapons/laserimpact.wav", 1, ATTN_NORM);
\r
173 self.think = GrapplingHookThink;
\r
174 self.nextthink = time + 0.1;
\r
175 self.touch = SUB_Null;
\r
176 self.velocity = '0 0 0';
\r
177 self.movetype = MOVETYPE_NONE;
\r
179 if((other.classname == "player" || other.classname == "body") && other.health > 0)
\r
181 self.enemy = other;
\r
184 Damage (other, self, self.owner, cvar("g_balance_grapple_damage"), WEP_GRAPPLE, self.origin, normalize(self.velocity)*cvar("g_balance_grapple_force"));
\r
187 void FireGrapplingHook (void)
\r
190 // fixme: drop the CTF flag
\r
193 local entity missile;
\r
196 makevectors(self.v_angle);
\r
198 sound (self, CHAN_WEAPON, "weapons/lasergun_fire.wav", 1, ATTN_NORM);
\r
199 org = self.origin + self.view_ofs + v_forward * 15 - v_right * 5 + v_up * -12;
\r
200 te_customflash(org, 160, 0.2, '1 0 0');
\r
202 missile = spawn ();
\r
203 missile.owner = self;
\r
204 self.hook = missile;
\r
205 missile.classname = "laserbolt";
\r
207 missile.movetype = MOVETYPE_FLY;
\r
208 missile.solid = SOLID_BBOX;
\r
210 setmodel (missile, "models/ebomb.mdl");//laser.mdl");
\r
211 setsize (missile, '0 0 0', '0 0 0');
\r
212 setorigin (missile, org);
\r
214 missile.state = 0; // not latched onto anything
\r
216 missile.velocity = v_forward * cvar("g_balance_grapple_speed");
\r
217 missile.angles = vectoangles (missile.velocity);
\r
218 //missile.glow_color = 250; // 244, 250
\r
219 //missile.glow_size = 120;
\r
220 missile.touch = GrapplingHookTouch;
\r
221 missile.think = GrapplingHookThink;
\r
222 missile.nextthink = time + 0.1;
\r
224 missile.effects = EF_FULLBRIGHT | EF_ADDITIVE | EF_LOWPRECISION;
\r
227 void GrapplingHookFrame()
\r
229 // if I have no hook or it's not pulling yet, make sure I'm not flying!
\r
230 if((self.hook == world || !self.hook.state) && self.movetype == MOVETYPE_FLY && self.health > 2)
\r
232 self.movetype = MOVETYPE_WALK;
\r
236 // remove hook, reset movement type
\r
237 RemoveGrapplingHook(self);
\r
240 // note: The hook entity does the actual pulling
\r
243 void() grapple_ready_01 = {weapon_thinkf(WFRAME_IDLE, 0.1, grapple_ready_01); self.weaponentity.state = WS_READY;};
\r
244 void() grapple_select_01 = {weapon_thinkf(-1, cvar("g_balance_weaponswitchdelay"), w_ready); weapon_boblayer1(PLAYER_WEAPONSELECTION_SPEED, '0 0 0');};
\r
245 void() grapple_deselect_01 = {weapon_thinkf(-1, cvar("g_balance_weaponswitchdelay"), w_clear); weapon_boblayer1(PLAYER_WEAPONSELECTION_SPEED, PLAYER_WEAPONSELECTION_RANGE);};
\r
246 void() grapple_fire1_01 =
\r
248 weapon_doattack(grapple_check, grapple_check, FireGrapplingHook);
\r
249 weapon_thinkf(WFRAME_FIRE1, 0.3, grapple_ready_01);
\r