1 2 3 void() SUB_Null = {}; 4 5 void() SUB_Remove = {remove(self);}; 6 7 8 /* 9 QuakeEd only writes a single float for angles (bad idea), so up and down are 10 just constant angles. 11 */ 12 vector() SetMovedir = 13 { 14 if (self.angles == '0 -1 0') 15 self.movedir = '0 0 1'; 16 else if (self.angles == '0 -2 0') 17 self.movedir = '0 0 -1'; 18 else 19 { 20 makevectors (self.angles); 21 self.movedir = v_forward; 22 } 23 24 self.angles = '0 0 0'; 25 }; 26 27 /* 28 ================ 29 InitTrigger 30 ================ 31 */ 32 void() InitTrigger = 33 { 34 // trigger angles are used for one-way touches. An angle of 0 is assumed 35 // to mean no restrictions, so use a yaw of 360 instead. 36 if (self.angles != '0 0 0') 37 SetMovedir (); 38 self.solid = SOLID_TRIGGER; 39 setmodel (self, self.model); // set size and link into world 40 self.movetype = MOVETYPE_NONE; 41 self.modelindex = 0; 42 self.model = ""; 43 }; 44 45 /* 46 ============= 47 SUB_CalcMove 48 49 calculate self.velocity and self.nextthink to reach dest from 50 self.origin traveling at speed 51 =============== 52 */ 53 void(entity ent, vector tdest, float tspeed, void() func) SUB_CalcMoveEnt = 54 { 55 local entity stemp; 56 stemp = self; 57 self = ent; 58 59 SUB_CalcMove (tdest, tspeed, func); 60 self = stemp; 61 }; 62 63 void(vector tdest, float tspeed, void() func) SUB_CalcMove = 64 { 65 local vector vdestdelta; 66 local float len, traveltime; 67 68 if (!tspeed) 69 objerror("No speed is defined!"); 70 71 self.think1 = func; 72 self.finaldest = tdest; 73 self.think = SUB_CalcMoveDone; 74 75 if (tdest == self.origin) 76 { 77 self.velocity = '0 0 0'; 78 self.nextthink = self.ltime + 0.1; 79 return; 80 } 81 82 // set destdelta to the vector needed to move 83 vdestdelta = tdest - self.origin; 84 85 // calculate length of vector 86 len = vlen (vdestdelta); 87 88 // divide by speed to get time to reach dest 89 traveltime = len / tspeed; 90 91 if (traveltime < 0.03) 92 traveltime = 0.03; 93 94 // set nextthink to trigger a think when dest is reached 95 self.nextthink = self.ltime + traveltime; 96 97 // scale the destdelta vector by the time spent traveling to get velocity 98 self.velocity = vdestdelta * (1/traveltime); // qcc won't take vec/float 99 }; 100 101 /* 102 ============ 103 After moving, set origin to exact final destination 104 ============ 105 */ 106 void() SUB_CalcMoveDone = 107 { 108 setorigin(self, self.finaldest); 109 self.velocity = '0 0 0'; 110 self.nextthink = -1; 111 if (self.think1) 112 self.think1(); 113 }; 114 115 116 /* 117 ============= 118 SUB_CalcAngleMove 119 120 calculate self.avelocity and self.nextthink to reach destangle from 121 self.angles rotating 122 123 The calling function should make sure self.think is valid 124 =============== 125 */ 126 void(entity ent, vector destangle, float tspeed, void() func) SUB_CalcAngleMoveEnt = 127 { 128 local entity stemp; 129 stemp = self; 130 self = ent; 131 SUB_CalcAngleMove (destangle, tspeed, func); 132 self = stemp; 133 }; 134 135 void(vector destangle, float tspeed, void() func) SUB_CalcAngleMove = 136 { 137 local vector destdelta; 138 local float len, traveltime; 139 140 if (!tspeed) 141 objerror("No speed is defined!"); 142 143 // set destdelta to the vector needed to move 144 destdelta = destangle - self.angles; 145 146 // calculate length of vector 147 len = vlen (destdelta); 148 149 // divide by speed to get time to reach dest 150 traveltime = len / tspeed; 151 152 // set nextthink to trigger a think when dest is reached 153 self.nextthink = self.ltime + traveltime; 154 155 // scale the destdelta vector by the time spent traveling to get velocity 156 self.avelocity = destdelta * (1 / traveltime); 157 158 self.think1 = func; 159 self.finalangle = destangle; 160 self.think = SUB_CalcAngleMoveDone; 161 }; 162 163 /* 164 ============ 165 After rotating, set angle to exact final angle 166 ============ 167 */ 168 void() SUB_CalcAngleMoveDone = 169 { 170 self.angles = self.finalangle; 171 self.avelocity = '0 0 0'; 172 self.nextthink = -1; 173 if (self.think1) 174 self.think1(); 175 }; 176 177 178 //============================================================================= 179 180 void() DelayThink = 181 { 182 activator = self.enemy; 183 SUB_UseTargets (); 184 remove(self); 185 }; 186 187 /* 188 ============================== 189 SUB_UseTargets 190 191 the global "activator" should be set to the entity that initiated the firing. 192 193 If self.delay is set, a DelayedUse entity will be created that will actually 194 do the SUB_UseTargets after that many seconds have passed. 195 196 Centerprints any self.message to the activator. 197 198 Removes all entities with a targetname that match self.killtarget, 199 and removes them, so some events can remove other triggers. 200 201 Search for (string)targetname in all entities that 202 match (string)self.target and call their .use function 203 204 ============================== 205 */ 206 void() SUB_UseTargets = 207 { 208 local entity t, stemp, otemp, act; 209 210 // 211 // check for a delay 212 // 213 if (self.delay) 214 { 215 // create a temp object to fire at a later time 216 t = spawn(); 217 t.classname = "DelayedUse"; 218 t.nextthink = time + self.delay; 219 t.think = DelayThink; 220 t.enemy = activator; 221 t.message = self.message; 222 t.killtarget = self.killtarget; 223 t.target = self.target; 224 return; 225 } 226 227 228 // 229 // print the message 230 // 231 if (activator.classname == "player" && self.message != "") 232 { 233 centerprint (activator, self.message); 234 if (!self.noise) 235 sound (activator, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM); 236 } 237 238 // 239 // kill the killtagets 240 // 241 if (self.killtarget) 242 { 243 t = world; 244 do 245 { 246 t = find (t, targetname, self.killtarget); 247 if (!t) 248 return; 249 remove (t); 250 } while ( 1 ); 251 } 252 253 // 254 // fire targets 255 // 256 if (self.target) 257 { 258 act = activator; 259 t = world; 260 do 261 { 262 t = find (t, targetname, self.target); 263 if (!t) 264 { 265 return; 266 } 267 stemp = self; 268 otemp = other; 269 self = t; 270 other = stemp; 271 if (self.use != SUB_Null) 272 { 273 if (self.use) 274 self.use (); 275 } 276 self = stemp; 277 other = otemp; 278 activator = act; 279 } while ( 1 ); 280 } 281 282 283 }; 284 285