/* */ void (entity targ, entity inflictor, entity attacker, float damage) T_Damage; void () player_run; void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage; void(vector org, vector vel, float damage) SpawnBlood; void() SuperDamageSound; void() player_stand1; // entity values for chasecam purposes .vector last_roll; .entity chasecam; .float tracking_speed; .float chasecam_zoom; .float last_weapon_channel; float DEFAULT_TRACKING_SPEED = 0; vector CHASECAM_CLOSE = '16 0 16'; //vector CHASECAM_FAR = '20 0 48'; float chasecam_alt, chasecam_dist = 16, chasecam_zofs = 6; // called by worldspawn void() W_Precache = { precache_sound ("weapons/r_exp3.wav"); // new rocket explosion precache_sound ("weapons/rocket1i.wav"); // spike gun precache_sound ("weapons/sgun1.wav"); precache_sound ("weapons/guncock.wav"); // player shotgun precache_sound ("weapons/ric1.wav"); // ricochet (used in c code) precache_sound ("weapons/ric2.wav"); // ricochet (used in c code) precache_sound ("weapons/ric3.wav"); // ricochet (used in c code) precache_sound ("weapons/spike2.wav"); // super spikes precache_sound ("weapons/tink1.wav"); // spikes tink (used in c code) precache_sound ("weapons/grenade.wav"); // grenade launcher precache_sound ("weapons/bounce.wav"); // grenade bounce precache_sound ("weapons/shotgn2.wav"); // super shotgun }; float() crandom = { return 2*(random() - 0.5); }; /* ================ W_FireAxe ================ */ void() W_FireAxe = { local vector source; local vector org; self.punchangle_y = -8; self.punchangle_x = -4; self.punchangle_z = 0; makevectors (self.v_angle); source = self.origin + '0 0 16'; traceline (source, source + v_forward*64, FALSE, self); if (trace_fraction == 1.0) return; org = trace_endpos - v_forward*4; if (trace_ent.takedamage) { trace_ent.axhitme = 1; SpawnBlood (org, '0 0 0', 20); T_Damage (trace_ent, self, self, 20); } else { // hit wall sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM); WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_GUNSHOT); WriteCoord (MSG_BROADCAST, org_x); WriteCoord (MSG_BROADCAST, org_y); WriteCoord (MSG_BROADCAST, org_z); } }; //============================================================================ vector() wall_velocity = { local vector vel; /* vel = normalize (self.velocity); vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5)); vel = vel + 2*trace_plane_normal; vel = vel * 200; */ makevectors(other.angles); vel = normalize(v_forward*(random() - 0.85) + v_up*(random() - 0.5) + v_right*(random() - 0.5)); vel = vel * 300; return vel; }; //float SLIDE_SPEED = 1; void() BloodWallSlide = { local vector pt1; if (self.attack_finished < time) { remove(self); return; } pt1 = self.origin + self.v_angle*8; traceline(pt1, pt1 - '0 0 0.5', TRUE, self); if (trace_fraction < 1) { remove(self); return; } pt1 = trace_endpos; traceline(pt1, pt1 - (self.v_angle*12), TRUE, self); setorigin(self, trace_endpos); //bprint("blood wall slide\n"); self.last_blood_think = time; self.nextthink = time + 0.1; }; void() BloodTouch = { local vector dir; if (other != world) { remove(self); return; } //bprint("blood touch\n"); dir = normalize(self.velocity); makevectors(dir); traceline(self.origin - dir*4, self.origin + dir*12, TRUE, self); if ((trace_fraction < 1) && (fabs(trace_plane_normal_z) < 0.2)) { // start sliding down wall self.movetype = MOVETYPE_NONE; self.velocity = '0 0 0'; self.v_angle = trace_plane_normal; self.last_blood_think = time; self.frame = self.frame + 1; self.think = BloodWallSlide; self.nextthink = time + 0.1; self.attack_finished = time + 7; self.angles = vectoangles(trace_plane_normal); } }; /* ================ SpawnMeatSpray ================ */ void(vector org, vector vel) SpawnMeatSpray = { local entity missile, mpuff; local vector org; missile = spawn (); missile.owner = self; missile.movetype = MOVETYPE_BOUNCE; missile.solid = SOLID_BBOX; makevectors (self.angles); missile.velocity = vel; missile.velocity_z = missile.velocity_z + 150 + 50*random(); missile.avelocity = '300 100 200'; missile.touch = BloodTouch; // set missile duration missile.nextthink = time + 5; missile.think = SUB_Remove; setmodel (missile, "progs/blood.mdl"); setsize (missile, '0 0 0', '0 0 0'); setorigin (missile, org); }; /* ================ SpawnBlood ================ */ void(vector org, vector vel, float damage) SpawnBlood = { local vector vrand, vect; local float num_gibs; particle (org, vel* -0.1, 73, damage*2); if (deathmatch) { // preserve bandwidth return; } num_gibs = ceil(damage / 15); while (num_gibs > 0) { vrand = '8 0 0' * random() + '0 8 0' * random() + '0 0 4' * random() - '4 4 2'; vect = normalize(vrand + vel); SpawnMeatSpray(org + vect*24, vect*(100 + random()*400)); num_gibs = num_gibs - 1; } }; /* ================ spawn_touchblood ================ */ void(float damage) spawn_touchblood = { local vector vel, vrand; local float num_gibs; vel = wall_velocity () * 0.2; if (deathmatch) { SpawnBlood (self.origin + vel*0.01, vel, damage); return; } num_gibs = damage / 10; while (num_gibs > 0) { vrand = '8 0 0' * random() + '0 8 0' * random() + '0 0 4' * random() - '4 4 2'; SpawnMeatSpray(self.origin + vrand + vel*0.01, vel + vrand*20); num_gibs = num_gibs - 1; } }; /* ================ SpawnChunk ================ */ void(vector org, vector vel) SpawnChunk = { // particle (org, vel*0.02, 0, 10); SpawnBlood(org, vel*0.02, 5); }; /* ============================================================================== MULTI-DAMAGE Collects multiple small damages into a single damage ============================================================================== */ entity multi_ent; float multi_damage; void() ClearMultiDamage = { multi_ent = world; multi_damage = 0; }; void() ApplyMultiDamage = { if (!multi_ent) return; T_Damage (multi_ent, self, self, multi_damage); }; void(entity hit, float damage) AddMultiDamage = { if (!hit) return; if (hit != multi_ent) { ApplyMultiDamage (); multi_damage = damage; multi_ent = hit; } else multi_damage = multi_damage + damage; }; /* ============================================================================== BULLETS ============================================================================== */ /* ================ TraceAttack ================ */ void(entity ent, float num_gibs) IcemanShardGib; void(float damage, vector dir) TraceAttack = { local vector vel, org; vel = normalize(dir*5 + v_up*random() + v_right*crandom()); // vel = vel + 2*trace_plane_normal; // vel = normalize(vel); org = trace_endpos - dir*4; if (trace_ent.takedamage) { org = trace_ent.origin; if ((trace_ent.classname != "xmen_sinister") || (trace_ent.x_flags & X_MEGA_HIT)) { if ((trace_ent.classname != "xmen_iceman") && (trace_ent.character != CHAR_ICEMAN)) { if ((trace_ent.flags & FL_MONSTER) || (trace_ent.flags & FL_CLIENT)) { if (random() < 0.8) SpawnBlood (org, vel * 12, damage); else SpawnBlood (org, vel * -2, damage); } } else { IcemanShardGib(trace_ent, damage / 6); } } AddMultiDamage (trace_ent, damage); } else { WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_GUNSHOT); WriteCoord (MSG_BROADCAST, org_x); WriteCoord (MSG_BROADCAST, org_y); WriteCoord (MSG_BROADCAST, org_z); } }; /* ================ FireBullets Used by shotgun, super shotgun, and enemy soldier firing Go to the trouble of combining multiple pellets into a single damage call. ================ */ void(float shotcount, vector dir, vector spread) FireBullets = { local vector direction; local vector src; makevectors(self.v_angle); src = self.origin + v_forward*10 + '0 0 12'; src_z = self.absmin_z + self.size_z * 0.7; ClearMultiDamage (); while (shotcount > 0) { direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up; traceline (src, src + direction*2048, FALSE, self); if (trace_fraction != 1.0) TraceAttack (4, direction); shotcount = shotcount - 1; } ApplyMultiDamage (); }; /* ================ W_FireShotgun ================ */ void() W_FireShotgun = { local vector dir; sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM); self.punchangle_x = -2; self.currentammo = self.ammo_shells = self.ammo_shells - 1; dir = aim (self, 100000); FireBullets (6, dir, '0.04 0.04 0'); }; /* ================ W_FireSuperShotgun ================ */ void() W_FireSuperShotgun = { local float rnd; local vector dir; if (self.currentammo <= 1) self.currentammo = self.ammo_shells = 0; else self.currentammo = self.ammo_shells = self.ammo_shells - 1; sound (self ,CHAN_WEAPON, "weapons/shotfir6.wav", 1, ATTN_NORM); self.punchangle_x = -8; dir = aim (self, 100000); FireBullets (7, dir, '0.06 0.06 0'); if (vlen(self.velocity) < 10) { // add some bounce if stationery self.velocity = self.velocity + '0 0 150'; } v_forward_z = 0; self.velocity = self.velocity - (v_forward * 40); }; /* ============================================================================== ROCKETS ============================================================================== */ void() s_explode1 = [0, s_explode2] {}; void() s_explode2 = [1, s_explode3] {self.effects = self.effects | EF_DIMLIGHT;}; void() s_explode3 = [2, s_explode4] {}; void() s_explode4 = [3, s_explode5] {self.effects = self.effects - EF_DIMLIGHT;}; void() s_explode5 = [4, s_explode6] {}; void() s_explode6 = [5, SUB_Remove] {}; void() BecomeExplosion = { self.movetype = MOVETYPE_NONE; self.velocity = '0 0 0'; self.touch = SUB_Null; setmodel (self, "progs/s_explod.spr"); self.solid = SOLID_NOT; s_explode1 (); }; void() T_MissileTouch = { local float damg; if (other == self.owner) return; // don't explode on owner if (pointcontents(self.origin) == CONTENT_SKY) { remove(self); return; } damg = 100 + random()*20; if (other.health) { if (other.classname == "xmen_storm") damg = damg * 0.5; // mostly immune T_Damage (other, self, self.owner, damg ); } // don't do radius damage to the other, because all the damage // was done in the impact T_RadiusDamage (self, self.owner, 120, other); // sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM); self.origin = self.origin - 8*normalize(self.velocity); WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_EXPLOSION); WriteCoord (MSG_BROADCAST, self.origin_x); WriteCoord (MSG_BROADCAST, self.origin_y); WriteCoord (MSG_BROADCAST, self.origin_z); BecomeExplosion (); }; void() cannon_xatta16; void() T_GuidedMissileTouch = { local float damg; if (other == self.owner) return; // don't explode on owner if (pointcontents(self.origin) == CONTENT_SKY) { remove(self); return; } if (self.dmg == 0) damg = 35 + random()*5; else damg = self.dmg; if (self.classname == "dm_phoenix_blast") damg = damg / 2; if (self.classname == "phoenix_blast") damg = damg / 2; if ((other.classname == "xmen_cannonball") && (other.flags & FL_GODMODE)) { if (other.last_rocket_hit > (time - 0.5)) { other.x_flags = other.x_flags | X_CANNONFLYABORT; // other.think = cannon_xatta16; } } if (other != world) other.last_rocket_hit = time; if (other.health) { if (!(other.x_flags & X_ANGEL_DEFENSE)) T_Damage (other, self, self.owner, damg ); if ((other.movetype) && (other.flags & FL_ONGROUND) && (other.classname != "apocalypse_small") && (other.classname != "xmen_sinister")) { // give some velocity other.velocity = other.velocity + normalize(self.velocity) * 180; if (other.velocity_z < 140) other.velocity_z = 140; other.flags = other.flags - (other.flags & FL_ONGROUND); setorigin(other, other.origin + '0 0 1'); } } if (self.classname != "phoenix_blast") { // don't do radius damage to the other, because all the damage // was done in the impact T_RadiusDamage (self, self.owner, 40, other); } sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 0.6, ATTN_NORM); self.origin = self.origin - 8*normalize(self.velocity); BecomeExplosion (); }; /******************************* FindSightEnemy Returns an entity that is within "angle_range" of "dir" use filter_classname to exclude all entitys with the given classname from being returned (use "world" to for to include all classes) *******************************/ entity(vector org, vector dir, float dist, float angle_range, string filter_class, entity ignore) FindSightEnemy = { local entity trav; local float trav_yaw, dir_yaw; dir_yaw = vectoyaw(dir); trav = findradius(org, dist); while (trav != world) { if (((filter_class == "all") || (filter_class == trav.classname)) && (trav != ignore) && ((ignore != world) && (trav != ignore.owner))) { if ((trav.takedamage == DAMAGE_AIM) && (trav.health > 0)) { // make sure trav is within the angle_range trav_yaw = vectoyaw(trav.origin - org); if (fabs(angle_diff(dir_yaw, trav_yaw)) <= angle_range) { // check there is a clear line of sight traceline(org, trav.origin, TRUE, world); if (trace_fraction == 1) { return trav; } } } } trav = trav.chain; } return trav; }; void() T_MissileTouch; // lower weight, means more accurate void(vector target_org, float weight) RocketSeek = { local float current_speed; local vector target_vector, vel, unit_velocity; current_speed = vlen(self.velocity); target_vector = normalize(target_org - self.origin); unit_velocity = normalize(self.velocity); self.velocity = normalize(target_vector + unit_velocity*weight) * current_speed; vel = normalize(self.velocity); self.angles = vectoangles(vel); self.nextthink = time + 0.05; }; void() GuidedRocketThink = { local vector dir, new_targ, reflect, endpos; local float interdist; if (self.attack_finished < time) { remove(self); return; } dir = normalize(self.velocity); self.angles = vectoangles(dir); self.angles_x = -1 * self.angles_x; if (self.classname == "prox_missile") particle(self.origin, self.velocity * 0.5, 44, 10); if (self.enemy != world) { if ((self.enemy.health <= 0) || ((self.enemy.classname == "xmen_phoenix") && (self.enemy.flags & FL_GODMODE))) { self.enemy = world; } else { traceline(self.origin, self.enemy.origin, TRUE, self); if (trace_fraction == 1) { // clear path if (self.classname == "prox_missile") RocketSeek(self.enemy.origin, 0.5); else if (self.classname == "dm_phoenix_blast") RocketSeek(self.enemy.origin, 8); else RocketSeek(self.enemy.origin, 5); return; } } } else if ((self.enemy == world) && (self.last_guided_search < (time - 0.2))) // search for a new target every 0.5 seconds { makevectors(self.angles); dir = v_forward; if (self.classname == "pheonix_blast") self.enemy = FindSightEnemy(self.origin, dir, 1500, 30, "player", self); else self.enemy = FindSightEnemy(self.origin, dir, 1500, 30, "all", self); self.last_guided_search = time; } // avoid walls dir = normalize(self.velocity); traceline(self.origin, self.origin + dir*256, TRUE, self); if ((trace_fraction < 1) && (trace_ent == world)) { // heading for a wall endpos = trace_endpos; interdist = 256 * trace_fraction; // reflect = GetReflectionVect(trace_endpos, dir, trace_plane_normal); new_targ = endpos + trace_plane_normal * interdist; RocketSeek(new_targ, 3); return; } self.nextthink = time + 0.05; }; void() GuidedRocketStart = { local entity missile_enemy; local vector dir; dir = normalize(self.velocity); if (self.enemy == world) { if ((missile_enemy = FindSightEnemy(self.origin, dir, 1500, 30, "all", self.owner)) != world) { self.enemy = missile_enemy; if (missile_enemy.th_guard) { if (missile_enemy.enemy == self.owner) { // alert Enemy missile_enemy.guard_flag = TRUE; } } } else { self.velocity = self.old_velocity + normalize(self.velocity) * 3; self.velocity = normalize(self.velocity); self.angles = vectoangles(self.velocity); self.angles_x = -1 * self.angles_x; self.velocity = self.velocity * 500; } } self.think = GuidedRocketThink; self.nextthink = time + 0.05; }; void(vector origdir, vector ofs) GuidedMissile = { local entity missile, missile_enemy; local vector dir; missile = spawn (); missile.classname = "guided_rocket"; missile.attack_finished = time + 3; missile.owner = self; missile.movetype = MOVETYPE_FLYMISSILE; missile.solid = SOLID_BBOX; // dir = normalize(origdir); dir = v_forward; if ((missile_enemy = FindSightEnemy(missile.origin, dir, 1500, 30, "all", self)) != world) { self.enemy = missile_enemy; if (missile_enemy.th_guard) { if (missile_enemy.enemy == self) { // alert Enemy missile_enemy.guard_flag = TRUE; } } } missile.think = GuidedRocketStart; missile.last_guided_search = time; missile.nextthink = time + 0.3; missile.old_velocity = normalize(origdir); // set missile speed missile.velocity = dir; missile.velocity = missile.velocity * 500; missile.angles = vectoangles(missile.velocity); missile.touch = T_GuidedMissileTouch; setmodel (missile, "progs/missmall.mdl"); setsize (missile, '0 0 0', '0 0 0'); setorigin (missile, self.origin + origdir + ofs + v_forward * 8 + '0 0 16'); }; void() W_FireGuidedRockets = { if (self.ammo_rockets <= 2) self.currentammo = self.ammo_rockets = 0; else self.currentammo = self.ammo_rockets = self.ammo_rockets - 2; sound (self, CHAN_WEAPON, "weapons/guidfire.wav", 1, ATTN_NORM); self.punchangle_x = -12; makevectors (self.v_angle); /* GuidedMissile(v_forward*3 + v_up); GuidedMissile(v_forward*3 + v_right); GuidedMissile(v_forward*3 - v_right); */ // GuidedMissile(v_forward*5 - v_right); // GuidedMissile(v_forward*5 + v_right); GuidedMissile(v_right * 2, v_right * 6); GuidedMissile(v_right * -2, v_right * 6); }; /* ================ W_FireRocket ================ */ void() W_FireRocket = { local entity missile, mpuff; // self.currentammo = self.ammo_rockets = self.ammo_rockets - 3; // sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM); self.punchangle_x = -2; missile = spawn (); missile.owner = self; missile.movetype = MOVETYPE_FLYMISSILE; missile.solid = SOLID_BBOX; missile.classname = "missile"; // set missile speed makevectors (self.v_angle); missile.velocity = aim(self, 1000); missile.velocity = missile.velocity * 1000; missile.angles = vectoangles(missile.velocity); missile.touch = T_MissileTouch; // set missile duration missile.nextthink = time + 5; missile.think = SUB_Remove; setmodel (missile, "progs/missile.mdl"); setsize (missile, '0 0 0', '0 0 0'); setorigin (missile, self.origin + v_forward*8 + '0 0 16'); W_FireGuidedRockets(); }; /* =============================================================================== LIGHTNING =============================================================================== */ .float remove_time; void() bolt_think = { self.angles_z = random() * 340 - 170; if (self.remove_time < time) { remove(self); return; } self.frame = self.speed; self.nextthink = time + 0.05; }; void(vector start, vector end, string modelstr, vector angle_ofs, float bolt_life) FillBetweenPoints = { local vector org, dir, dir_angle; local float dist; local entity newbolt; dist = vlen(start - end); dir = normalize(end - start); dir_angle = vectoangles(dir); org = start; while (vlen(org - start) < dist) { //bprint("b"); newbolt = spawn(); setmodel(newbolt, modelstr); setorigin(newbolt, org); newbolt.frame = 0; //frame_num; newbolt.speed = 0; //frame_num; newbolt.angles = dir_angle + angle_ofs; newbolt.angles_z = random() * 340 - 170; newbolt.remove_time = time + bolt_life; //0.07; newbolt.think = bolt_think; newbolt.nextthink = time + 0.05; if (modelstr == "progs/bolt3.mdl") org = org + dir*128; else org = org + dir*32; } //bprint("\n"); }; /* ================= LightningDamage ================= */ void(vector p1, vector p2, entity from, float damage) LightningDamage = { local entity e1, e2; local vector f; f = p2 - p1; normalize (f); f_x = 0 - f_y; f_y = f_x; f_z = 0; f = f*16; e1 = e2 = world; traceline (p1, p2, FALSE, self); if (trace_ent.takedamage) { particle (trace_endpos, '0 0 100', 225, damage*4); T_Damage (trace_ent, from, from, damage); if (self.classname == "player") { if (other.classname == "player") trace_ent.velocity_z = trace_ent.velocity_z + 400; } } e1 = trace_ent; traceline (p1 + f, p2 + f, FALSE, self); if (trace_ent != e1 && trace_ent.takedamage) { particle (trace_endpos, '0 0 100', 225, damage*4); T_Damage (trace_ent, from, from, damage); } e2 = trace_ent; traceline (p1 - f, p2 - f, FALSE, self); if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage) { particle (trace_endpos, '0 0 100', 225, damage*4); T_Damage (trace_ent, from, from, damage); } }; void(vector org_start, vector dir_start) ReflectLightning = { local float reflect_count, NUM_REFLECTIONS, frac, total_dist, MAX_DIST, length; local vector org, dir, normal, endpos; local entity ent, junction; local string str; NUM_REFLECTIONS = 2; MAX_DIST = 800; org = org_start; dir = dir_start; reflect_count = 0; total_dist = 0; junction = self; while (reflect_count <= NUM_REFLECTIONS) { traceline (org, org + dir*600, FALSE, self); frac = trace_fraction; ent = trace_ent; normal = trace_plane_normal; endpos = trace_endpos; length = vlen(endpos - org); if ((total_dist + length) > MAX_DIST) { endpos = org + dir * (MAX_DIST - total_dist); reflect_count = NUM_REFLECTIONS; } // if (trace_fraction < 0.05) // return; WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_LIGHTNING2); WriteEntity (MSG_BROADCAST, junction); WriteCoord (MSG_BROADCAST, org_x); WriteCoord (MSG_BROADCAST, org_y); WriteCoord (MSG_BROADCAST, org_z); WriteCoord (MSG_BROADCAST, endpos_x); WriteCoord (MSG_BROADCAST, endpos_y); WriteCoord (MSG_BROADCAST, endpos_z); LightningDamage (org, endpos + dir*4, self, 30 * (1 - (total_dist/480))); // lose power over distance //str = ftos(frac); //bprint(str); //bprint("\n"); if ((frac < 1) && (ent == world)) { org = endpos; dir = GetReflectionVect(org, dir, normal); reflect_count = reflect_count + 1; } else { reflect_count = NUM_REFLECTIONS + 1; total_dist = MAX_DIST; } // junction = junction.beam_ent; } }; void() W_FireLightning = { local vector org; local float cells; stuffcmd(self, "bf\n"); self.punchangle = '-10 0 0' + '10 0 0' * random() + '0 10 0' * random() + '0 0 10' * random() - '5 5 5'; // self.currentammo = self.ammo_cells = self.ammo_cells - 1; org = self.origin + '0 0 16'; makevectors(self.v_angle); traceline(org, org + v_forward * 1000, FALSE, self); WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_LIGHTNING2); WriteEntity (MSG_BROADCAST, self); WriteCoord (MSG_BROADCAST, org_x); WriteCoord (MSG_BROADCAST, org_y); WriteCoord (MSG_BROADCAST, org_z); WriteCoord (MSG_BROADCAST, trace_endpos_x); WriteCoord (MSG_BROADCAST, trace_endpos_y); WriteCoord (MSG_BROADCAST, trace_endpos_z); if ((trace_ent != world) && !(trace_ent.x_flags & X_MEGA_HIT) && ((trace_ent.owner.classname == "xmen_apocalypse") || (trace_ent.classname == "xmen_sinister"))) { T_Damage(trace_ent, self, self, 5000); } }; void() ProximityAttack = { local vector vect; local float dist; local entity ent, oself; if (other == world) { remove(self); return; } if (other != self.enemy) return; ent = self.enemy; // oself = self; // self = self.owner; vect = normalize(ent.origin - self.oldorigin); dist = vlen(ent.origin - self.oldorigin); if (dist > 200) dist = 200; if ((ent.classname != "apocalypse_small") && (ent.classname != "xmen_sinister")) ent.velocity = ent.velocity + vect * (200 - dist) + '0 0 180'; ent.flags = ent.flags - (ent.flags & FL_ONGROUND); WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_EXPLOSION); WriteCoord (MSG_BROADCAST, ent.origin_x); WriteCoord (MSG_BROADCAST, ent.origin_y); WriteCoord (MSG_BROADCAST, ent.origin_z); SpawnBlood (ent.origin, '0 0 0', 20); if ((ent.classname == "xmen_sinister") || (ent.classname == "apocalypse_small")) self.prox_power = self.prox_power / 5; T_Damage(ent, self, self.owner, ent.start_health * (self.prox_power / 100) + 10); // self = oself; remove(self); }; void() ProximityThink = { // remove if player is dead if ((self.owner.health <= 0) || (self.modelindex == index_skeleton) || (intermission_running)) { self.owner.prox_ent = world; remove(self); return; } if (self.owner.last_prox_think < (time - 5)) { self.owner.prox_ent = world; remove(self); return; } self.frame = self.frame + 1; if (self.frame > 5) self.frame = 0; if (self.last_flame_sound < (time - 0.75)) { if (random() < 0.5) sound(self, CHAN_AUTO, "weapons/prox1.wav", self.owner.prox_power / 100, ATTN_NORM); else sound(self, CHAN_AUTO, "weapons/prox2.wav", self.owner.prox_power / 100, ATTN_NORM); self.last_flame_sound = time; } if (self.last_flame < (time - 0.05)) { // increase power if ((self.owner.currentammo > 0) && (self.owner.prox_power < 100)) { self.owner.currentammo = self.owner.ammo_cells = self.owner.ammo_cells - 1; self.owner.prox_power = self.owner.prox_power + 1; if ((self.owner.currentammo > 0) && (self.owner.prox_power < 100)) { self.owner.currentammo = self.owner.ammo_cells = self.owner.ammo_cells - 1; self.owner.prox_power = self.owner.prox_power + 1; } if ((self.owner.currentammo > 0) && (self.owner.prox_power < 100)) { self.owner.currentammo = self.owner.ammo_cells = self.owner.ammo_cells - 1; self.owner.prox_power = self.owner.prox_power + 1; } // faster under rapid fire if ((self.owner.x_flags & X_RAPID_FIRE) && (self.owner.currentammo > 0) && (self.owner.prox_power < 100)) { self.owner.currentammo = self.owner.ammo_cells = self.owner.ammo_cells - 1; self.owner.prox_power = self.owner.prox_power + 1; } if ((self.owner.x_flags & X_RAPID_FIRE) && (self.owner.currentammo > 0) && (self.owner.prox_power < 100)) { self.owner.currentammo = self.owner.ammo_cells = self.owner.ammo_cells - 1; self.owner.prox_power = self.owner.prox_power + 1; } if ((self.model == "progs/atom1.mdl") && (self.owner.prox_power > 40)) setmodel(self, "progs/atom2.mdl"); else if ((self.model == "progs/atom2.mdl") && (self.owner.prox_power > 70)) setmodel(self, "progs/atom3.mdl"); self.last_flame = time; } else if ((self.owner.prox_power >= 50) && (self.last_flame < (time - 3))) { T_Damage(self.owner, world, world, 2); self.last_flame = time - 2; // next hurt after 1 seconds only } } if (self.movetype != MOVETYPE_BOUNCE) { // align with owner makevectors(self.owner.v_angle); setorigin(self, self.owner.origin + v_forward * 24 + '0 0 22'); } self.nextthink = time + 0.01; }; void() StartProximity = { local entity prox; if (self.prox_ent != world) { remove(self.prox_ent); self.prox_ent = world; } prox = spawn(); self.prox_ent = prox; prox.classname = "proximity_ball"; prox.owner = self; prox.spawn_time = time; prox.movetype = MOVETYPE_FLY; prox.avelocity = '100 0 0' * random() + '0 100 0' * random() + '0 0 100' * random() - '50 50 50'; setmodel(prox, "progs/atom1.mdl"); self.last_prox_think = time; prox.think = ProximityThink; self = prox; ProximityThink(); self = self.owner; }; void(entity targ) SpawnProxMissile = { local entity missile; local vector dir, vect; missile = spawn (); missile.classname = "prox_missile"; missile.attack_finished = time + 3; missile.owner = self.owner; missile.oldorigin = self.origin; missile.movetype = MOVETYPE_FLYMISSILE; missile.solid = SOLID_BBOX; missile.prox_power = self.owner.prox_power; dir = normalize(targ.origin - self.origin); dir = normalize('0 0 1' + dir * 5); missile.enemy = targ; missile.think = GuidedRocketStart; missile.nextthink = time + 0.05; missile.old_velocity = dir; // set missile speed missile.velocity = dir; missile.velocity = missile.velocity * 750; missile.angles = vectoangles(missile.velocity); missile.touch = ProximityAttack; setmodel (missile, "progs/atomshot.mdl"); setsize (missile, '0 0 0', '0 0 0'); vect = normalize(self.velocity); setorigin (missile, self.origin - vect * 8); }; void() ProximityTouch = { local entity trav, expthink; local float num; if (other == self.owner) return; sound(self, CHAN_ITEM, "items/damage2.wav", 1, ATTN_NORM); // sound(self, CHAN_BODY, "weapons/r_exp3.wav", 0.4, ATTN_NORM); num = rint(6 * (self.prox_power / 100)) + 2; trav = findradius(self.origin, 800); while ((trav != world) && (num > 0)) { if ((trav.takedamage) && (trav != self.owner)) { // check visibility traceline(self.origin, trav.origin, TRUE, trav); if ((trace_fraction == 1) || (trace_ent == trav)) { if (((trav.classname != "xmen_sinister") || (self.x_flags & X_MEGA_HIT)) && (trav.classname != "xmen_apocalypse")) { SpawnProxMissile(trav); num = num - 1; } /* expthink = spawn(); expthink.enemy = trav; expthink.owner = self.owner; expthink.prox_power = self.prox_power; expthink.think = ProximityAttack; expthink.nextthink = time + vlen(trav.origin - self.origin) / 400; */ // ProximityAttack(trav); } } trav = trav.chain; } if (other.takedamage) T_Damage(other, self, self, self.owner.prox_power); WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_EXPLOSION); WriteCoord (MSG_BROADCAST, self.origin_x); WriteCoord (MSG_BROADCAST, self.origin_y); WriteCoord (MSG_BROADCAST, self.origin_z); BecomeExplosion (); self.owner.prox_ent = world; }; void() W_FireProximity = { local vector org; local float cells; local entity trav, expthink; /* if (self.ammo_cells < 1) { self.weapon = W_BestWeapon (); W_SetCurrentAmmo (); return; } if (self.ammo_cells > 50) { cells = 50; self.currentammo = self.ammo_cells = self.ammo_cells - 50; } else { cells = self.ammo_cells; self.currentammo = self.ammo_cells = 0; } */ if (self.prox_ent == world) // nothing to throw return; // Throw the proxmity ball self.prox_ent.solid = SOLID_TRIGGER; self.prox_ent.movetype = MOVETYPE_FLYMISSILE; setsize(self.prox_ent, '0 0 0', '0 0 0'); self.prox_ent.touch = ProximityTouch; self.prox_ent.prox_power = self.prox_power; self.prox_ent.think = SUB_Null; makevectors(self.v_angle); // self.prox_ent.velocity = self.velocity + (v_forward*2 + v_up*0.5) * 50 + '0 0 80'; self.prox_ent.velocity = v_forward * 750; self.attack_finished = time + 2; // stuffcmd(self, "bf\n"); sound(self, CHAN_ITEM, "cannon/takeoff.wav", 1, ATTN_NORM); /* sound(self, CHAN_WEAPON, "items/damage2.wav", 1, ATTN_NORM); sound(self, CHAN_BODY, "weapons/r_exp3.wav", 0.4, ATTN_NORM); trav = findradius(self.origin, 800); while (trav != world) { if ((trav.takedamage) && (trav != self)) { // check visibility traceline(self.origin, trav.origin, TRUE, trav); if ((trace_fraction == 1) || (trace_ent == trav)) { expthink = spawn(); expthink.enemy = trav; expthink.owner = self; expthink.think = ProximityAttack; expthink.nextthink = time + vlen(trav.origin - self.origin) / 400; // ProximityAttack(trav); } } trav = trav.chain; } */ }; //============================================================================= void() GrenadeExplode = { T_RadiusDamage (self, self.owner, 60, world); /* WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_EXPLOSION); WriteCoord (MSG_BROADCAST, self.origin_x); WriteCoord (MSG_BROADCAST, self.origin_y); WriteCoord (MSG_BROADCAST, self.origin_z); */ if ((other.movetype) && (other.flags & FL_ONGROUND) && (other.classname != "xmen_sinister") && (other.classname != "apocalypse_small")) { // give some velocity other.velocity = other.velocity + normalize(self.velocity) * 100 + '0 0 220'; other.flags = other.flags - (other.flags & FL_ONGROUND); setorigin(other, other.origin + '0 0 1'); } sound(self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM); BecomeExplosion (); }; void() GrenadeTouch = { if (other == self.owner) return; // don't explode on owner if ((other.classname == "xmen_phoenix") && (other.flags & FL_GODMODE)) return; if ((other.takedamage == DAMAGE_AIM) && !(other.x_flags & X_ANGEL_DEFENSE)) { GrenadeExplode(); return; } sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound if (self.velocity == '0 0 0') self.avelocity = '0 0 0'; }; /* ================ W_FireGrenade ================ */ void() W_FireGrenade = { local entity missile, mpuff, phoenix; if (self.ammo_rockets > 0) self.currentammo = self.ammo_rockets = self.ammo_rockets - 1; sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM); self.punchangle_x = -2; missile = spawn (); missile.owner = self; missile.movetype = MOVETYPE_BOUNCE; missile.solid = SOLID_BBOX; missile.classname = "orb"; // set missile speed makevectors (self.v_angle); if (self.v_angle_x) missile.velocity = v_forward*900 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10; else { missile.velocity = aim(self, 10000); missile.velocity = missile.velocity * 900; missile.velocity_z = 200; } missile.avelocity = '300 300 300'; missile.angles = vectoangles(missile.velocity); missile.touch = GrenadeTouch; // set missile duration missile.nextthink = time + 2.5; missile.think = GrenadeExplode; setmodel (missile, "progs/orb1.mdl"); setsize (missile, '0 0 0', '0 0 0'); setorigin (missile, self.origin + v_right * 6 + v_forward * 16); missile.old_velocity = missile.velocity; // check for Pheonix defence phoenix = find(world, classname, "xmen_phoenix"); while (phoenix != world) { if (phoenix.enemy == self) phoenix.guard_flag = TRUE; phoenix = find(phoenix, classname, "xmen_phoenix"); } }; //============================================================================= void() spike_touch; void() superspike_touch; /* =============== launch_spike Used for both the player and the ogre =============== */ void(vector org, vector dir) launch_spike = { newmis = spawn (); newmis.owner = self; newmis.movetype = MOVETYPE_FLYMISSILE; newmis.solid = SOLID_BBOX; newmis.angles = vectoangles(dir); newmis.touch = spike_touch; newmis.classname = "spike"; newmis.think = SUB_Remove; newmis.nextthink = time + 6; setmodel (newmis, "progs/spike.mdl"); setsize (newmis, VEC_ORIGIN, VEC_ORIGIN); setorigin (newmis, org); newmis.velocity = dir * 1000; }; void(float ox) W_FireSuperSpikes = { local vector dir; local entity old; local string sample; local float shells; sample = "weapons/chnfire5.wav"; if (self.last_weapon_channel != CHAN_WEAPON) { sound (self, CHAN_WEAPON, sample, 1, ATTN_NORM); self.last_weapon_channel = CHAN_WEAPON; } else { sound (self, CHAN_ITEM, sample, 1, ATTN_NORM); self.last_weapon_channel = CHAN_ITEM; } self.attack_finished = time + 0.2; if (random() < 0.5) shells = 1; else shells = 2; dir = aim (self, 100000); if (self.ammo_shells <= shells) { self.currentammo = self.ammo_shells = 0; } else { self.currentammo = self.ammo_shells = self.ammo_shells - shells; } FireBullets (shells, dir, '0.04 0.04 0'); /* self.currentammo = self.ammo_shells = self.ammo_shells - 1; dir = aim (self, 1000); launch_spike (self.origin + '0 0 16' + ox * v_right, dir); newmis.touch = superspike_touch; setmodel (newmis, "progs/s_spike.mdl"); setsize (newmis, VEC_ORIGIN, VEC_ORIGIN); */ self.punchangle_x = -2; }; void(float ox) W_FireSpikes = { local vector dir; local entity old; makevectors (self.v_angle); if (self.weapon == IT_SHOTGUN) { W_FireSuperSpikes (); return; } if (self.ammo_nails < 1) { self.weapon = W_BestWeapon (); W_SetCurrentAmmo (); return; } sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM); self.attack_finished = time + 0.2; self.currentammo = self.ammo_nails = self.ammo_nails - 1; dir = aim (self, 1000); launch_spike (self.origin + '0 0 16' + v_right*ox, dir); self.punchangle_x = -2; }; /* =============== Lazer Gun stuff =============== */ void() Flameball_Touch = { local vector org; if (other == self.owner) return; // don't explode on owner if (pointcontents(self.origin) == CONTENT_SKY) { remove(self); return; } // sound (self, CHAN_WEAPON, "enforcer/enfstop.wav", 1, ATTN_STATIC); org = self.origin - 8*normalize(self.velocity); if ((other.health) && (other.classname != "xmen_bishop")) { SpawnBlood (org, self.velocity*0.2, 12); T_Damage (other, self, self.owner, 12); } else { WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_GUNSHOT); WriteCoord (MSG_BROADCAST, org_x); WriteCoord (MSG_BROADCAST, org_y); WriteCoord (MSG_BROADCAST, org_z); } self.origin = self.origin - 8*normalize(self.velocity); BecomeExplosion (); }; void() FlameballThink = { self.angles_z = (random() * 360) - 180; if (self.spawn_time < (time - 6)) { remove(self); return; } self.nextthink = time + 0.1; }; void(vector org, vector dir) Launch_Flameball = { newmis = spawn (); newmis.owner = self; newmis.movetype = MOVETYPE_FLYMISSILE; newmis.solid = SOLID_BBOX; newmis.angles = vectoangles(dir); newmis.touch = Flameball_Touch; newmis.classname = "flameball"; newmis.think = FlameballThink; newmis.nextthink = time + 0.1; setmodel (newmis, "progs/flamball.mdl"); setsize (newmis, VEC_ORIGIN, VEC_ORIGIN); setorigin (newmis, org); newmis.spawn_time = time; newmis.angles_z = (random() * 360) - 180; newmis.velocity = dir * 1500; }; // X-Men: fires a laser projectile void(float ox) W_FireFlameball = { local vector dir; local entity old; local string sample; makevectors (self.v_angle); sample = "weapons/f_start.wav"; if (self.last_weapon_channel != CHAN_WEAPON) { sound (self, CHAN_WEAPON, sample, 1, ATTN_NORM); self.last_weapon_channel = CHAN_WEAPON; } else { sound (self, CHAN_ITEM, sample, 1, ATTN_NORM); self.last_weapon_channel = CHAN_ITEM; } if (self.ammo_nails < 1) { self.weapon = W_BestWeapon (); W_SetCurrentAmmo (); return; } // sound (self, CHAN_WEAPON, "enforcer/enfire.wav", 1, ATTN_NORM); self.attack_finished = time + 0.2; self.currentammo = self.ammo_nails = self.ammo_nails - 1; dir = v_forward; Launch_Flameball (self.origin + '0 0 16' + v_right*4, dir); self.punchangle_x = -2; }; .float hit_z; void() spike_touch = { local float rand, damg; local vector vect; if ((other == self.owner) || (other.owner == self.owner)) return; if (other.solid == SOLID_TRIGGER) return; // trigger field, do nothing if (pointcontents(self.origin) == CONTENT_SKY) { remove(self); return; } // hit something that bleeds if (other.takedamage) { if (!self.dmg) damg = 9; else damg = self.dmg; spawn_touchblood (damg); T_Damage (other, self, self.owner, damg); remove(self); return; } else if (self.classname == "angel_dart") { vect = normalize(self.velocity); setorigin(self, self.origin + vect*2); self.velocity = '0 0 0'; self.solid = SOLID_NOT; self.movetype = MOVETYPE_NONE; self.think = SUB_Remove; self.nextthink = time + 5; WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_SPIKE); WriteCoord (MSG_BROADCAST, self.origin_x); WriteCoord (MSG_BROADCAST, self.origin_y); WriteCoord (MSG_BROADCAST, self.origin_z); return; } WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); if (self.classname == "wizspike") WriteByte (MSG_BROADCAST, TE_WIZSPIKE); else if (self.classname == "gambit_card") WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE); else WriteByte (MSG_BROADCAST, TE_SPIKE); WriteCoord (MSG_BROADCAST, self.origin_x); WriteCoord (MSG_BROADCAST, self.origin_y); WriteCoord (MSG_BROADCAST, self.origin_z); remove(self); }; void() superspike_touch = { local float rand; if (other == self.owner) return; if (other.solid == SOLID_TRIGGER) return; // trigger field, do nothing if (pointcontents(self.origin) == CONTENT_SKY) { remove(self); return; } // hit something that bleeds if (other.takedamage) { spawn_touchblood (18); T_Damage (other, self, self.owner, 18); } else { WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_SUPERSPIKE); WriteCoord (MSG_BROADCAST, self.origin_x); WriteCoord (MSG_BROADCAST, self.origin_y); WriteCoord (MSG_BROADCAST, self.origin_z); } remove(self); }; /* ================ W_FireFlameThrower ================ */ void(float num_bubbles) DeathBubbles; void() W_FireFlameThrower = { local string sample; if (self.classname == "player") { if (self.ammo_nails < 1) { self.weapon = W_BestWeapon (); W_SetCurrentAmmo (); return; } if (self.ammo_nails < 4) self.ammo_nails = 0; else self.ammo_nails = self.ammo_nails - 4; self.currentammo = self.ammo_nails; if (self.waterlevel >= 3) { // can't fire while underwater self.flags = self.flags - (self.flags & FL_FLAMEON); self.water_flame_flag = TRUE; DeathBubbles(1); return; } } sample = "weapons/flame.wav"; if (self.last_flame_sound < (time - SNDLEN_FLAME)) { if (self.last_weapon_channel != CHAN_WEAPON) { sound (self, CHAN_WEAPON, sample, 1, ATTN_NORM); self.last_weapon_channel = CHAN_WEAPON; } else { sound (self, CHAN_ITEM, sample, 1, ATTN_NORM); self.last_weapon_channel = CHAN_ITEM; } self.last_flame_sound = time + (random() * 0.2) - 0.05; } if (!(self.flags & FL_FLAMEON)) { //bprint("starting flame..\n"); setorigin(self.flame_ent1, self.origin + v_forward * 16); setorigin(self.flame_ent2, self.origin + v_forward * 16); setorigin(self.flame_ent3, self.origin + v_forward * 96); self.flame_ent1.nextthink = time + 0.05; self.flame_ent1.speed = 0; self.flame_ent2.speed = 0; self.flame_ent3.speed = 0; setmodel(self.flame_ent1, "progs/fl_th1.mdl"); setmodel(self.flame_ent2, "progs/null.spr"); setmodel(self.flame_ent3, "progs/fl_th5.mdl"); } if (self.water_flame_flag) { self.flags = self.flags | FL_FLAMEON; self.water_flame_flag = FALSE; } self.last_flame = time; }; void(entity ent, vector pos, float dist) movetopos = { local vector vect; if (vlen(ent.origin - pos) > dist) { vect = normalize(pos - ent.origin); setorigin(ent, ent.origin + vect * dist); } else { setorigin(ent, pos); } }; void(vector p1, vector p2) FlameParticles = { local float rcol, rnd; local vector vect, avect, rvect, org, vel; // random color between 228 - 233 rnd = random(); rcol = 228 + floor(rnd * 2); // do vector stuff vect = normalize(p2 - p1); avect = vectoangles(vect); avect_x = -1 * vect_x; makevectors(avect); rvect = ('1 0 0' * random()) + ('0 1 0' * random()) + ('0 0 1' * random()) - '0.5 0.5 0.5'; org = p1 + v_forward * 32 + v_forward * rnd * FLAME_DIST * 0.5; vel = normalize(v_forward + (rvect * 0.3) + '0 0 0.2') * 20; particle( org, v_forward * 10, 235, 20); particle( org, vel, rcol, 50); // flame_ent_think() requires the following line.. makevectors(self.owner.v_angle); }; void() flame_ent_think = { local entity ent, ent_parent; local vector vect, ideal_pnt, ofs, oldangles; local float this_dist, this_speed, dist_from, dist1, dist2, short_flag; local entity ent_burn; short_flag = FALSE; // set flame distance if (!(self.owner.flags & FL_FLAMEON)) { //bprint("stopping flame..\n"); // if ((vlen(self.origin - self.owner.origin) < 32) || // (self.owner.last_flame < (time - 1))) { // flame has run out setmodel(self.owner.flame_ent1, string_null); setmodel(self.owner.flame_ent2, string_null); setmodel(self.owner.flame_ent3, string_null); self.owner.flame_ent1.effects = 0; self.owner.flame_ent2.effects = 0; self.owner.flame_ent3.effects = 0; self.nextthink = -1; return; // } this_dist = -2 * FLAME_DIST; self.speed = self.speed - (FLAME_ENT_SPEED * frametime * 0.5); if (self.speed < 0) self.speed = 0; } else { this_dist = FLAME_DIST; } self.nextthink = time + 0.05; ent_burn = world; makevectors(self.owner.v_angle); ofs = v_forward * 32 + v_right * 10 + '0 0 36' - v_up * 28; if (self.owner.character == CHAR_STORM) ofs_z = ofs_z + STORM_VOFS_Z; // move 1st junction to ideal position **************************************************** ent = self; ent_parent = self.owner; traceline(ent_parent.origin + ofs - v_forward * 32, ent_parent.origin + ofs + v_forward * this_dist * 0.5, FALSE, self.owner); dist_from = vlen(ent.origin - trace_endpos); // ent.angles = vectoangles(v_forward); // ent.angles_z = (360 * random()) - 180; ent.angles = self.owner.v_angle; ent.angles_x = -1 * ent.angles_x; ent.angles_z = random() * 360 - 180; movetopos(ent, trace_endpos, FLAME_ENT_SPEED * frametime); /* FlameParticles(ent.owner.origin + ofs * 2 - '0 0 4', ent.origin); FlameParticles(ent.owner.origin + ofs * 2 - '0 0 4', ent.origin); FlameParticles(ent.owner.origin + ofs * 2 - '0 0 4', ent.origin); */ // fill with flame bits // FillBetweenPoints(ent_parent.origin + ofs, ent.origin, "progs/fl_th1.mdl", '0 0 0', 0.07); // ent.effects = ent.effects | EF_MUZZLEFLASH; if (ent.speed < FLAME_DIST) { ent.speed = ent.speed + (FLAME_ENT_SPEED * frametime * 0.5); if (ent.speed > FLAME_DIST) ent.speed = FLAME_DIST; } if (trace_fraction < 1) { setorigin(self.owner.flame_ent2, ent.origin); self.owner.flame_ent2.speed = 0; setorigin(self.owner.flame_ent3, ent.origin); self.owner.flame_ent3.speed = 0; if ((trace_ent != world) && (trace_ent.takedamage)) { ent_burn = trace_ent; } short_flag = TRUE; } // T_RadiusDamage(ent, self.owner, 10, self.owner); // move 2nd junction to ideal position **************************************************** ent_parent = self.owner.flame_ent1; ent = self.owner.flame_ent2; traceline(ent_parent.origin - v_forward * 2, ent_parent.origin + v_forward * this_dist, FALSE, self.owner); dist_from = vlen(ent.origin - trace_endpos); if (dist_from < 4) ent.angles = vectoangles('0 0 1'); else { vect = normalize(ent.origin - trace_endpos); ent.angles = vectoangles(vect); } ent.angles_z = (360 * random()) - 180; this_speed = FLAME_ENT_SPEED * (dist_from / 64); if (this_speed > (FLAME_ENT_SPEED * 2)) this_speed = FLAME_ENT_SPEED*2; movetopos(ent, trace_endpos, dist_from / 2); //this_speed * frametime); // movetopos(ent, trace_endpos, this_speed * frametime); if (trace_fraction == 1) { vect = normalize(ent.origin - ent_parent.origin); setorigin(ent, ent_parent.origin + (vect * ent.speed)); } // FlameParticles(ent.owner.origin, ent.origin); // fill with flame bits dist_from = vlen(ent.origin - ent_parent.origin); if (dist_from > 32) FillBetweenPoints(ent_parent.origin, ent.origin - v_forward * 30, "progs/fl_th2.mdl", '0 0 0', 0.07); ent.effects = ent.effects | EF_DIMLIGHT; if (ent.speed < FLAME_DIST) { ent.speed = ent.speed + (FLAME_ENT_SPEED * frametime * 0.5); if (ent.speed > FLAME_DIST * 0.75) ent.speed = FLAME_DIST * 0.75; } if (trace_fraction < 1) { setorigin(self.owner.flame_ent3, ent.origin); self.owner.flame_ent3.speed = 0; if ((trace_ent != world) && (trace_ent.takedamage)) { ent_burn = trace_ent; } short_flag = TRUE; } if (deathmatch) T_RadiusDamage(ent, self.owner, 15, self.owner); else T_RadiusDamage(ent, self.owner, 10, self.owner); // move 3rd junction to ideal position **************************************************** v_forward = vect; ent_parent = self.owner.flame_ent2; ent = self.owner.flame_ent3; ideal_pnt = ent_parent.origin + v_forward * this_dist * 0.75; traceline(ent_parent.origin - v_forward * 2, ideal_pnt, FALSE, self.owner); dist_from = vlen(ent.origin - trace_endpos); // if (dist_from < 4) // ent.angles = vectoangles('0 0 1'); // else { // vect = normalize(ent.origin - trace_endpos); // ent.angles = vectoangles(vect); // } // ent.angles_z = (360 * random()) - 180; ent.frame = random() * 5.9; ent.frame = floor(ent.frame); dist_from = vlen(ent.origin - ideal_pnt); //trace_endpos); this_speed = FLAME_ENT_SPEED * (dist_from / 256); if (this_speed > (FLAME_ENT_SPEED * 2)) this_speed = FLAME_ENT_SPEED*2; this_speed = this_speed * 3; ent.oldorigin = ent.origin; movetopos(ent, trace_endpos, dist_from / 3); //this_speed * frametime); if (vlen(ent.origin - ent_parent.origin) > this_dist * 0.75) { vect = normalize(ent.origin - ent_parent.origin); setorigin(ent, ent_parent.origin + (vect * this_dist * 0.75)); } oldangles = ent.angles; if ((trace_fraction == 1) && (!short_flag)) { vect = normalize(ent.origin - ent_parent.origin); ent.angles = vectoangles(vect); if (ent.model != "progs/fl_th5.mdl") setmodel(ent, "progs/fl_th5.mdl"); } else { vect = normalize(ent.origin - self.owner.origin); ent.angles = vectoangles(vect); // ent.angles_x = ent.angles_x + 45; if (ent.model != "progs/fl_th6.mdl") setmodel(ent, "progs/fl_th6.mdl"); } // ent.angles_x = -1 * ent.angles_x; // calculate Z rotation to match "sway" movement makevectors(ent.angles); vect = ent.origin - ent.oldorigin; dist1 = vlen(vect + v_right); dist2 = vlen(vect - v_right); if ((!short_flag) && (vlen(vect) > 4)) { if ((dist1 - dist2) > 0) { // moving towards RIGHT ent.angles_z = MoveToAngle(oldangles_z, 320, 500); } else if ((dist1 - dist2) < 0) { // moving towards LEFT ent.angles_z = MoveToAngle(oldangles_z, 40, 500); } } else { // move towards 0 ent.angles_z = MoveToAngle(oldangles_z, 0, 500); } vect = normalize(ent.origin - ent.owner.origin); dist_from = vlen(vect); /* if ((vlen(ent.origin - self.owner.origin) > FLAME_DIST) || (trace_fraction < 1)) { // if (trace_fraction == 1) { // vect = normalize(ent.origin - ent_parent.origin); // setorigin(ent, ent_parent.origin + (vect * ent.speed)); // } if (ent.model != "progs/fl_th3.mdl") setmodel(ent, "progs/fl_th3.mdl"); } else { if (ent.model != "progs/fl_th2.mdl") setmodel(ent, "progs/fl_th2.mdl"); } */ // FlameParticles(ent.owner.origin, ent.origin); // fill with flame bits // FillBetweenPoints(ent_parent.origin + vect * (dist_from / 2), ent.origin, "progs/fl_th3.mdl", '45 0 0', 0.07); ent.effects = ent.effects | EF_DIMLIGHT; if (ent.speed < FLAME_DIST) { ent.speed = ent.speed + (FLAME_ENT_SPEED * frametime * 0.5); if (ent.speed > FLAME_DIST * 0.5) ent.speed = FLAME_DIST * 0.5; } if ((trace_ent != world) && (trace_ent.takedamage)) { ent_burn = trace_ent; } if (deathmatch) T_RadiusDamage(ent, self.owner, 20, self.owner); else T_RadiusDamage(ent, self.owner, 13, self.owner); if (ent_burn != world && deathmatch) { T_Damage(trace_ent, self.owner, self.owner, 8); } }; void() SetSpecialWeaponModel = { if (self.character == CHAR_WOLVERINE) { self.weaponmodel = "progs/v_wol.mdl"; } else if (self.character == CHAR_STORM) { self.weaponmodel = "progs/v_sto.mdl"; } else if (self.character == CHAR_CYCLOPS) { self.weaponmodel = "progs/v_cyc.mdl"; } else if (self.character == CHAR_PSYLOCKE) { self.weaponmodel = "progs/v_psy.mdl"; } else if (self.character == CHAR_ANGEL) { self.weaponmodel = "progs/v_ang.mdl"; } else if (self.character == CHAR_BEAST) { self.weaponmodel = "progs/v_bea.mdl"; } else if (self.character == CHAR_GAMBIT) { self.weaponmodel = "progs/v_gam.mdl"; } else if (self.character == CHAR_ICEMAN) { self.weaponmodel = "progs/v_ice.mdl"; } else if (self.character == CHAR_BISHOP) { self.weaponmodel = "progs/v_bis.mdl"; } else if (self.character == CHAR_ROGUE) { self.weaponmodel = "progs/v_rog.mdl"; } else if (self.character == CHAR_CANNONBALL) { self.weaponmodel = "progs/v_can.mdl"; } else if (self.character == CHAR_PHOENIX) { self.weaponmodel = "progs/v_pho.mdl"; } else { self.weaponmodel = ""; sprint(self, "ERROR: Unknown character setting\n"); } }; /* =============================================================================== PLAYER WEAPON USE =============================================================================== */ void() SpecialWeaponChange; void() W_SetCurrentAmmo = { // player_run (); // get out of any weapon firing states if (self.modelindex == index_skeleton) return; self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) ); if (self.weapon == IT_AXE) { self.currentammo = 0; if (deathmatch || coop) { SetSpecialWeaponModel(); } else { self.weaponmodel = "progs/v_xfist.mdl"; } } else if (self.weapon == IT_SHOTGUN) { self.currentammo = self.ammo_shells; self.weaponmodel = "progs/v_xshot1.mdl"; self.items = self.items | IT_SHELLS; } else if (self.weapon == IT_SUPER_SHOTGUN) { self.currentammo = self.ammo_shells; self.weaponmodel = "progs/v_xchain.mdl"; self.items = self.items | IT_SHELLS; } else if (self.weapon == IT_NAILGUN) { self.currentammo = self.ammo_nails; self.weaponmodel = "progs/v_xfire1.mdl"; self.items = self.items | IT_NAILS; } else if (self.weapon == IT_SUPER_NAILGUN) { self.currentammo = self.ammo_nails; self.weaponmodel = "progs/v_xflame.mdl"; self.items = self.items | IT_NAILS; } else if (self.weapon == IT_GRENADE_LAUNCHER) { self.currentammo = self.ammo_rockets; self.weaponmodel = "progs/v_xorb.mdl"; self.items = self.items | IT_ROCKETS; } else if (self.weapon == IT_ROCKET_LAUNCHER) { self.currentammo = self.ammo_rockets; self.weaponmodel = "progs/v_xrock.mdl"; self.items = self.items | IT_ROCKETS; } else if (self.weapon == IT_LIGHTNING) { self.currentammo = self.ammo_cells; self.weaponmodel = "progs/v_xshock.mdl"; self.items = self.items | IT_CELLS; } else if (self.weapon == IT_SPECIAL_WEAPON) { self.currentammo = self.ammo_special; self.weaponmodel = "progs/v_xmega.mdl"; self.items = self.items | IT_CELLS; } else { self.currentammo = 0; self.weaponmodel = ""; } }; float() W_BestWeapon = { local float it; it = self.items; if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) ) return IT_LIGHTNING; else if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) ) return IT_ROCKET_LAUNCHER; else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) ) return IT_GRENADE_LAUNCHER; else if (self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) ) return IT_SUPER_NAILGUN; else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) ) return IT_SUPER_SHOTGUN; else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) ) return IT_NAILGUN; else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) ) return IT_SHOTGUN; return IT_AXE; }; float() W_CheckNoAmmo = { local float best; if (self.currentammo > 0) return TRUE; if (self.weapon == IT_AXE) return TRUE; // self.nextweapon = W_BestWeapon (); // best = W_BestWeapon (); // SetNewWeapon(best); // W_SetCurrentAmmo (); // drop the weapon down return FALSE; }; /* ============ W_Attack An attack impulse can be triggered now ============ */ void() player_att1; void() player_laser1; void() player_flame1; void() player_prox1; void() player_orb; void() player_rocket1; void() player_shotgun1; void() player_chain1; void() player_fist; void() player_mega; void() W_Attack = { local float r, best; if (self.modelindex == index_skeleton) return; if (self.change_weapon_status) { // no firing during fading // sprint(self, "can't fire, changing weapons\n"); return; } if (self.weapon_flags & W_RELOADING) { // sprint(self, "can't fire, reloading\n"); return; } if (!W_CheckNoAmmo ()) { best = W_BestWeapon (); SetNewWeapon(best); return; } /* if ((self.weapon == IT_NAILGUN) && (self.num_lasers >= 5)) return; else if ((self.num_lasers > 0) && (self.weapon != IT_NAILGUN)) self.num_lasers = 0; */ makevectors (self.v_angle); // calculate forward angle for velocity self.show_hostile = time + 1; // wake monsters up if (self.weapon == IT_AXE) { if (deathmatch || coop) { if ((!(self.weapon_flags & W_RELOADING)) && ((self.character != CHAR_CANNONBALL) || (self.last_special2 < (time - 1.5)))) { player_att1 (); } } else { player_fist(); } // self.attack_finished = time + 0.5; } else if (self.weapon == IT_SHOTGUN) { if (self.think != player_shotgun1) { self.weaponframe = 5; player_shotgun1 (); } self.attack_finished = time + 0.3; } else if (self.weapon == IT_SUPER_SHOTGUN) { if (self.weaponframe > 11) self.weaponframe = 6; if (time > self.w_pausetime) self.last_pausetime = 0; player_chain1 (); } else if (self.weapon == IT_NAILGUN) { // self.weaponmodel = "progs/v_xlas2.mdl"; // player_nail1 (); self.fire_reload_frames = 0; player_laser1 (); } else if (self.weapon == IT_SUPER_NAILGUN) { player_flame1(); self.attack_finished = time + 0.1; if (self.waterlevel < 3) { // can't fire while underwater if (!(self.flags & FL_FLAMEON)) sound(self, CHAN_BODY, "weapons/f_start.wav", 1, ATTN_NORM); self.flags = self.flags | FL_FLAMEON; } } else if (self.weapon == IT_GRENADE_LAUNCHER) { player_orb(); // W_FireGrenade(); } else if (self.weapon == IT_ROCKET_LAUNCHER) { player_rocket1(); // W_FireRocket(); W_FireGuidedRockets(); self.attack_finished = time + 1.6; } else if (self.weapon == IT_LIGHTNING) { // if (self.prox_ent != world) // return; player_prox1(); self.attack_finished = time + 0.2; // sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM); } else if (self.weapon == IT_SPECIAL_WEAPON) { player_mega(); self.attack_finished = time + 0.2; sound (self, CHAN_ITEM, "weapons/m_start.wav", 1, ATTN_NORM); sound (self, CHAN_WEAPON, "weapons/mega.wav", 1, ATTN_NONE); } }; float(float wpn) GetLastMoveFrame = { if (wpn == IT_SHOTGUN) return 25; if (wpn == IT_SUPER_SHOTGUN) return 12; if (wpn == IT_NAILGUN) return 15; if (wpn == IT_SUPER_NAILGUN) return 9; if (wpn == IT_GRENADE_LAUNCHER) return 18; if (wpn == IT_LIGHTNING) return 0; if (wpn == IT_ROCKET_LAUNCHER) return 17; if (wpn == IT_AXE) if (deathmatch || coop) return 0; else return 16; return 0; }; float(float wpn) GetFirstMoveFrame = { if (wpn == IT_SHOTGUN) return 30; // NOTE: frame 31 = frame 1 if (wpn == IT_SUPER_SHOTGUN) return 17; if (wpn == IT_NAILGUN) return 20; if (wpn == IT_SUPER_NAILGUN) return 15; if (wpn == IT_GRENADE_LAUNCHER) return 23; if (wpn == IT_LIGHTNING) return 4; if (wpn == IT_ROCKET_LAUNCHER) return 23; if (wpn == IT_AXE) if (deathmatch || coop) return 5; else return 22; return 0; }; // Return true if next weapon is on a different hand to the current weapon float() ChangingHands = { if ((deathmatch || coop) && (self.nextweapon == IT_AXE) && (self.weapon != IT_AXE)) return TRUE; if (self.nextweapon == IT_LIGHTNING) return TRUE; if (self.nextweapon == IT_SPECIAL_WEAPON) return TRUE; if ((self.nextweapon & (IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_AXE)) && (self.weapon & (IT_NAILGUN | IT_SUPER_NAILGUN | IT_ROCKET_LAUNCHER | IT_GRENADE_LAUNCHER))) { return TRUE; } if ((self.nextweapon & (IT_NAILGUN | IT_SUPER_NAILGUN | IT_ROCKET_LAUNCHER | IT_GRENADE_LAUNCHER)) && (self.weapon & (IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_AXE))) { return TRUE; } }; /* ================= FADE WEAPON OUT ================= */ void() FadeWeaponOut = { local float newframe; local string str; if (self.weapon_flags & W_RELOADING) return; if (self.chasecam != world) { // change immediately self.weapon = self.nextweapon; if (self.weapon == IT_AXE) SpecialWeaponChange(); W_SetCurrentAmmo (); self.weaponframe = newframe; self.change_weapon_status = CW_FADEIN; } self.last_fade = time; //bprint("fade out\n"); if (self.weapon & (IT_NAILGUN | IT_SUPER_NAILGUN | IT_ROCKET_LAUNCHER | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_AXE | IT_GRENADE_LAUNCHER)) { self.weaponframe = self.weaponframe - 1; if (self.weaponframe <= self.fadeout_endframe) { if ((self.fadeout_endframe == 0) && (ChangingHands()) && (GetLastMoveFrame(self.weapon) > 0)) { self.fadeout_endframe = GetLastMoveFrame(self.weapon); self.weaponframe = GetFirstMoveFrame(self.weapon); return; } // if we're still here then weapon must have completed fading out if (ChangingHands()) { newframe = GetLastMoveFrame(self.nextweapon); self.fadein_endframe = GetFirstMoveFrame(self.nextweapon); } else { newframe = 0; self.fadein_endframe = 5; // all morphing animations end at frame 5 } self.weapon = self.nextweapon; if (self.weapon == IT_AXE) SpecialWeaponChange(); W_SetCurrentAmmo (); self.weaponframe = newframe; self.change_weapon_status = CW_FADEIN; } } else { self.weaponframe = 0; self.weapon = self.nextweapon; if (self.weapon == IT_AXE) SpecialWeaponChange(); W_SetCurrentAmmo (); self.change_weapon_status = CW_FADEIN; } }; /* ================= FADE WEAPON IN ================= */ void() FadeWeaponIn = { local string str; if (self.chasecam != world) { // change immediately self.weaponframe = self.weapon_idleframe; self.change_weapon_status = CW_DONE; return; } self.last_fade = time; if (self.weapon & (IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_NAILGUN | IT_SUPER_NAILGUN | IT_AXE | IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER)) { self.weaponframe = self.weaponframe + 1; if (self.weaponframe >= self.fadein_endframe) { if (self.fadein_endframe >= 10) { // weapon has entered the screen self.fadein_endframe = self.weapon_idleframe; self.weaponframe = 0; } else { self.change_weapon_status = CW_DONE; } } } else if (self.weapon == IT_SPECIAL_WEAPON) { self.weaponframe = self.weaponframe + 1; if (self.weaponframe == 11) { self.change_weapon_status = CW_DONE; } } else { self.weaponframe = self.weapon_idleframe; self.change_weapon_status = CW_DONE; } }; // Starts the morphing towards the new weapon void(float wpn) SetNewWeapon = { // if (wpn & IT_LIGHTNING) { // return; // } if (deathmatch == DM_SPECIAL_POWERS) { self.weapon_idleframe = 6; return; } if ((self.think != player_run) && (self.think != player_stand1)) // only change if idle return; if (wpn == self.weapon) return; if ((self.weapon == IT_LIGHTNING) && (self.prox_ent != world)) return; // make sure we start at the idle frame self.weaponframe = self.weapon_idleframe; if ((deathmatch || coop) && (wpn == IT_AXE)) { self.weapon_idleframe = 6; } else { self.weapon_idleframe = 5; } self.nextweapon = wpn; self.change_weapon_status = CW_FADEOUT; self.fadeout_endframe = 0; FadeWeaponOut(); }; /* ============ W_ChangeWeapon ============ */ void() W_ChangeWeapon = { local float it, am, fl, new_idle; if (self.modelindex == index_skeleton) return; if ((deathmatch == DM_SPECIAL_POWERS) && (self.impulse != 1)) return; it = self.items; am = 0; if (self.impulse == 1) { fl = IT_AXE; new_idle = 6; if ((deathmatch || coop) && (self.weapon == IT_AXE)) { self.special_weapon = !self.special_weapon; } } else if (self.impulse == 2) { fl = IT_SHOTGUN; new_idle = 5; if (self.ammo_shells < 2) am = 1; } else if (self.impulse == 3) { fl = IT_SUPER_SHOTGUN; new_idle = 5; if (self.ammo_shells < 1) am = 1; } else if (self.impulse == 4) { fl = IT_NAILGUN; new_idle = 5; if (self.ammo_nails < 1) am = 1; } else if (self.impulse == 5) { fl = IT_SUPER_NAILGUN; if (self.ammo_nails < 2) am = 1; } else if (self.impulse == 6) { fl = IT_GRENADE_LAUNCHER; new_idle = 5; if (self.ammo_rockets < 1) am = 1; // not available yet } else if (self.impulse == 7) { fl = IT_ROCKET_LAUNCHER; new_idle = 5; if (self.ammo_rockets < 1) am = 1; } else if (self.impulse == 8) { fl = IT_LIGHTNING; new_idle = 2; if (self.ammo_cells < 1) am = 1; } else if (self.impulse == 13) // mega-weapon { fl = IT_SPECIAL_WEAPON; new_idle = 11; if (self.ammo_special < 1) am = 1; } self.impulse = 0; if ((!(self.items & fl)) && (deathmatch || coop)) // X-Men: in singleplayer, weapons are already present { // don't have the weapon or the ammo sprint (self, "no weapon.\n"); return; } if (am) { // don't have the ammo sprint (self, "not enough ammo.\n"); return; } // // set weapon, set ammo // // self.weapon_idleframe = new_idle; if (self.weapon != fl) SetNewWeapon(fl); else if (self.weapon == IT_AXE) { self.weapon = fl; SpecialWeaponChange(); W_SetCurrentAmmo (); } }; /* ============ CheatCommand ============ */ void() CheatCommand = // cheats disabled { if (deathmatch)// || coop) return; self.ammo_rockets = 100; self.ammo_nails = 200; self.ammo_shells = 150; self.items = self.items | IT_AXE | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_NAILGUN | IT_SUPER_NAILGUN | IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER | IT_KEY1 | IT_KEY2; self.ammo_cells = 200; self.items = self.items | IT_LIGHTNING; // SetNewWeapon(IT_ROCKET_LAUNCHER); // self.weapon = IT_ROCKET_LAUNCHER; self.impulse = 0; // W_SetCurrentAmmo (); }; /* ============ CycleWeaponCommand Go to the next weapon with ammo ============ */ void() CycleWeaponCommand = { local float it, am, fl; if (self.modelindex == index_skeleton) return; it = self.items; self.impulse = 0; fl = self.weapon; if (deathmatch == DM_SPECIAL_POWERS) { self.special_weapon = !self.special_weapon; self.weapon = fl; SpecialWeaponChange(); W_SetCurrentAmmo (); return; } while (1) { am = 0; if (fl == IT_LIGHTNING) { fl = IT_AXE; } else if (fl == IT_AXE) { fl = IT_SHOTGUN; if (self.ammo_shells < 1) am = 1; } else if (fl == IT_SHOTGUN) { fl = IT_SUPER_SHOTGUN; if (self.ammo_shells < 2) am = 1; } else if (fl == IT_SUPER_SHOTGUN) { fl = IT_NAILGUN; if (self.ammo_nails < 1) am = 1; } else if (fl == IT_NAILGUN) { fl = IT_SUPER_NAILGUN; if (self.ammo_nails < 2) am = 1; } else if (fl == IT_SUPER_NAILGUN) { fl = IT_GRENADE_LAUNCHER; if (self.ammo_rockets < 1) am = 1; } else if (fl == IT_GRENADE_LAUNCHER) { fl = IT_ROCKET_LAUNCHER; if (self.ammo_rockets < 1) am = 1; } else if (fl == IT_ROCKET_LAUNCHER) { fl = IT_LIGHTNING; if (self.ammo_cells < 1) am = 1; } if (am == 0) { SetNewWeapon(fl); // W_SetCurrentAmmo (); return; } } }; /* ============ CycleWeaponReverseCommand Go to the prev weapon with ammo ============ */ void() CycleWeaponReverseCommand = { local float it, am, fl; if (self.modelindex == index_skeleton) return; it = self.items; self.impulse = 0; fl = self.weapon; if (deathmatch == DM_SPECIAL_POWERS) { self.special_weapon = !self.special_weapon; self.weapon = fl; SpecialWeaponChange(); W_SetCurrentAmmo (); return; } while (1) { am = 0; if (fl == IT_LIGHTNING) { fl = IT_ROCKET_LAUNCHER; if (self.ammo_rockets < 1) am = 1; } else if (fl == IT_ROCKET_LAUNCHER) { fl = IT_GRENADE_LAUNCHER; if (self.ammo_rockets < 1) am = 1; } else if (fl == IT_GRENADE_LAUNCHER) { fl = IT_SUPER_NAILGUN; if (self.ammo_nails < 2) am = 1; } else if (fl == IT_SUPER_NAILGUN) { fl = IT_NAILGUN; if (self.ammo_nails < 1) am = 1; } else if (fl == IT_NAILGUN) { fl = IT_SUPER_SHOTGUN; if (self.ammo_shells < 2) am = 1; } else if (fl == IT_SUPER_SHOTGUN) { fl = IT_SHOTGUN; if (self.ammo_shells < 1) am = 1; } else if (fl == IT_SHOTGUN) { fl = IT_AXE; } else if (fl == IT_AXE) { fl = IT_LIGHTNING; if (self.ammo_cells < 1) am = 1; } if (am == 0) { SetNewWeapon(fl); // W_SetCurrentAmmo (); return; } } }; /* ============ ServerflagsCommand Just for development ============ */ void() ServerflagsCommand = { serverflags = serverflags * 2 + 1; }; void() QuadCheat = { if (deathmatch || coop) return; self.super_time = 1; self.super_damage_finished = time + 30; self.items = self.items | IT_QUAD; dprint ("quad cheat\n"); }; /* ============ Impulse Commands ============ */ float capture, last_capture, capture_count, capture_index; void() ImpulseCommands = { local float ftemp; local string str; if (self.impulse == 248) { capture = !capture; capture_index = 0; } if (!((self.change_weapon_status) || (self.weapon_flags & W_RELOADING) || ((self.think != player_run) && (self.think != player_stand1)))) { // weapon is ready for changing if (self.remember_impulse && (self.remember_impulse != 13)) { // prevent from changing while waiting for mega-weapon to come up self.impulse = self.remember_impulse; self.remember_impulse = 0; } if ((self.impulse >= 1 && self.impulse <= 8) || (self.impulse == 13)) W_ChangeWeapon (); else if (self.impulse == 10) CycleWeaponCommand (); else if (self.impulse == 12) CycleWeaponReverseCommand (); } else { if ((self.impulse <= 13) && (!self.remember_impulse)) self.remember_impulse = self.impulse; } if (!self.impulse) return; else if (self.impulse == 11) ServerflagsCommand (); else if (self.impulse == 20) // re-print last trigger_multiple/single message centerprint(self, self.last_centerprint); else if (self.impulse == 40) // toggle chasecam { if (self.chasecam == world) InitCam(self); else DisableCam(self); } // any impulses > 200 are debuggin only if (deathmatch) { self.impulse = 0; return; } else if (self.impulse == 99) CheatCommand (); else if (self.impulse == 200) show_damage = !show_damage; else if (self.impulse == 202) { // give all weapon parts self.weapon_parts = 4; serverflags = serverflags | 15; } else if (self.impulse == 250) { ftemp = cvar("coop") - 1; if (ftemp < 1) ftemp = 12; str = ftos(ftemp); cvar_set("coop", str); stuffcmd(self, "restart\n"); } else if (self.impulse == 251) { ftemp = cvar("coop") + 1; if (ftemp > 12) ftemp = 1; str = ftos(ftemp); cvar_set("coop", str); stuffcmd(self, "restart\n"); } else if (self.impulse == 222) { if (self.x_flags & X_GODCHEAT) { self.x_flags = self.x_flags - X_GODCHEAT; self.flags = self.flags - (self.flags & FL_GODMODE); stuffcmd(self, "bf\n"); sprint(self, "Invincibility disabled\n"); } else { self.x_flags = self.x_flags | X_GODCHEAT; self.flags = self.flags | FL_GODMODE; sprint(self, "Invincibility enabled\n"); } } // else if (self.impulse == 255) // QuadCheat (); self.impulse = 0; }; /* ============ W_WeaponFrame Called every frame so impulse events can be handled as well as possible ============ */ void() W_WeaponFrame = { if ((self.change_weapon_status) && (self.last_fade < (time - 0.07))) { if (self.change_weapon_status == CW_FADEOUT) FadeWeaponOut(); else FadeWeaponIn(); } ImpulseCommands (); if (time < self.attack_finished) return; if (self.change_weapon_status) return; // check for attack if ((self.button0) && (self.modelindex != index_skeleton)) { SuperDamageSound (); W_Attack (); if ((self.flags & FL_FLAMEON) && (self.weapon != IT_SUPER_NAILGUN)) { self.flags = self.flags - FL_FLAMEON; } } else { self.flags = self.flags - (self.flags & FL_FLAMEON); } }; /* ======== SuperDamageSound Plays sound if needed ======== */ void() SuperDamageSound = { if (self.super_damage_finished > time) { if (self.super_sound < time) { self.super_sound = time + 1; sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM); } } return; };