]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/gamec/g_hook.c
more changes from Wazat
[divverent/nexuiz.git] / qcsrc / gamec / g_hook.c
1 /*============================================
2
3       Wazat's Nexuiz Grappling Hook
4
5         Contact: Wazat1@gmail.com
6
7
8 Installation instructions:
9 --------------------------
10
11 1. Place hook.c in your gamec source directory with the other source files.
12
13 2. Add this line to the bottom of progs.src:
14
15 gamec/hook.c
16
17 3. Open defs.h and add these lines to the very bottom:
18
19 // Wazat's grappling hook
20 .entity         hook;
21 void GrapplingHookFrame();
22 void RemoveGrapplingHook(entity pl);
23 void SetGrappleHookBindings();
24 // hook impulses
25 float GRAPHOOK_FIRE             = 20;
26 float GRAPHOOK_RELEASE          = 21;
27 // (note: you can change the hook impulse #'s to whatever you please)
28
29 4. Open client.c and add this to the top of PutClientInServer(): 
30
31         RemoveGrapplingHook(self); // Wazat's Grappling Hook
32
33 5. Find ClientConnect() (in client.c) and add these lines to the bottom:
34
35         // Wazat's grappling hook
36         SetGrappleHookBindings();
37
38 6. Still in client.c, find PlayerPreThink and add this line just above the call to W_WeaponFrame:
39
40         GrapplingHookFrame();
41
42 7. Build and test the mod.  You'll want to bind a key to "+hook" like this:
43 bind ctrl "+hook"
44
45 And you should be done!
46
47
48 ============================================*/
49
50 void RemoveGrapplingHook(entity pl)
51 {
52         if(pl.hook == world)
53                 return;
54         remove(pl.hook);
55         pl.hook = world;
56         if(pl.movetype == MOVETYPE_FLY)
57                 pl.movetype = MOVETYPE_WALK;
58
59         pl.hook_time = time + 0.0;
60 }
61
62 void GrapplingHookThink()
63 {
64         float spd, dist, minlength, pullspeed;
65         vector dir, org, end;
66         if(self.owner.health <= 0 || self.owner.hook != self)   // how did that happen?
67         {                                                                                                               // well, better fix it anyway
68                 remove(self);
69                 return;
70         }
71
72         self.nextthink = time + 0.1;
73
74         makevectors(self.owner.v_angle);
75         org = self.owner.origin + self.owner.view_ofs + v_forward * 15 - v_right * 5 + v_up * -12;
76
77         if(self.state == 1)
78         {
79                 pullspeed = cvar("g_balance_grapplehook_speed_pull");//1000;
80                 minlength = 50;
81                 dir = self.origin - org;
82                 dist = vlen(dir);
83                 dir = normalize(dir);
84
85                 end = self.origin - dir*minlength;
86                 
87                 dist = vlen(end - org);
88
89                 if(dist < 200)
90                         spd = dist * (pullspeed / 200);
91                 else
92                         spd = pullspeed;
93                 if(spd < 50)
94                         spd = 0;
95
96                 self.owner.velocity = dir*spd;
97                 self.owner.movetype = MOVETYPE_FLY;
98                 self.owner.flags = self.owner.flags - (self.owner.flags & FL_ONGROUND);
99
100                 org = org + dir*50; // get the beam out of the player's eyes
101         }
102
103         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
104         WriteByte (MSG_BROADCAST, TE_BEAM);
105         WriteEntity (MSG_BROADCAST, self);
106         WriteCoord (MSG_BROADCAST, self.origin_x);
107         WriteCoord (MSG_BROADCAST, self.origin_y);
108         WriteCoord (MSG_BROADCAST, self.origin_z);
109         WriteCoord (MSG_BROADCAST, org_x);
110         WriteCoord (MSG_BROADCAST, org_y);
111         WriteCoord (MSG_BROADCAST, org_z);
112 }
113
114 void GrapplingHookTouch (void)
115 {
116         if (other == self.owner)
117                 return;
118         else if (pointcontents (self.origin) == CONTENT_SKY)
119         {
120                 RemoveGrapplingHook(self.owner);
121                 return;
122         }
123
124         self.event_damage = SUB_Null; // fixme: ability to dislodge a player by damaging hook?
125         sound (self, CHAN_BODY, "weapons/laserimpact.wav", 1, ATTN_NORM);
126
127         self.state = 1;
128         self.think = GrapplingHookThink;
129         self.nextthink = time + 0.1;
130         self.touch = SUB_Null;
131         self.velocity = '0 0 0';
132         self.movetype = MOVETYPE_NONE;
133 }
134
135 void FireGrapplingHook (void)
136 {
137         local entity missile;
138         local vector org;
139
140         makevectors(self.v_angle);
141
142         sound (self, CHAN_WEAPON, "weapons/lasergun_fire.wav", 1, ATTN_NORM);
143         org = self.origin + self.view_ofs + v_forward * 15 - v_right * 5 + v_up * -12;
144         te_customflash(org, 160, 0.2, '1 0 0');
145
146         missile = spawn ();
147         missile.owner = self;
148         self.hook = missile;
149         missile.classname = "laserbolt";
150
151         missile.movetype = MOVETYPE_FLY;
152         missile.solid = SOLID_BBOX;
153
154         setmodel (missile, "models/ebomb.mdl");//laser.mdl");
155         setsize (missile, '0 0 0', '0 0 0');
156         setorigin (missile, org);
157
158         missile.state = 0; // not latched onto anything
159
160         missile.velocity = v_forward * cvar("g_balance_grapplehook_speed_fly");
161         missile.angles = vectoangles (missile.velocity);
162         //missile.glow_color = 250; // 244, 250
163         //missile.glow_size = 120;
164         missile.touch = GrapplingHookTouch;
165         missile.think = GrapplingHookThink;
166         missile.nextthink = time + 0.1;
167
168         missile.effects = EF_FULLBRIGHT | EF_ADDITIVE | EF_LOWPRECISION;
169 }
170
171 void GrapplingHookFrame()
172 {
173         // if I have no hook or it's not pulling yet, make sure I'm not flying!
174         if((self.hook == world || !self.hook.state) && self.movetype == MOVETYPE_FLY)
175         {
176                 self.movetype = MOVETYPE_WALK;
177         }
178         if(self.impulse == GRAPHOOK_FIRE && self.hook_time <= time && cvar("g_grappling_hook"))
179         {
180                 // fire hook
181                 FireGrapplingHook();
182                 return;
183         }
184         else if(self.impulse == GRAPHOOK_RELEASE)
185         {
186                 // remove hook, reset movement type
187                 RemoveGrapplingHook(self);
188                 return;
189         }
190         /*else // make sure the player's movetype is correct
191         {
192                 //if(self.hook == world && self.movetype == MOVETYPE_FLY)
193                 if((self.hook == world || !self.hook.state) && self.movetype == MOVETYPE_FLY)
194                 {
195                         self.movetype = MOVETYPE_WALK;
196                 }
197         }*/
198         // note: The hook entity does the actual pulling
199 }
200
201 void SetGrappleHookBindings()
202 {
203         stuffcmd(self, strcat("alias +hook \"impulse ", ftos(GRAPHOOK_FIRE),    "\"\n"));
204         stuffcmd(self, strcat("alias -hook \"impulse ", ftos(GRAPHOOK_RELEASE), "\"\n"));
205 }