mirror of
https://github.com/nzp-team/quakec.git
synced 2024-11-10 06:31:44 +00:00
SERVER: Revamp Ray Gun logic and FX.
PC/FTE now usesa custom flash and low-level light to help it look a bit better. Damage values are more accurate, with detection for direct impact vs splash damage. Also moved into its own file to improve source readability.
This commit is contained in:
parent
5bee39d063
commit
b9246fff17
5 changed files with 192 additions and 97 deletions
|
@ -27,6 +27,7 @@
|
|||
../source/server/entities/machines.qc
|
||||
|
||||
../source/server/weapons/frames_core.qc
|
||||
../source/server/weapons/ray_gun.qc
|
||||
../source/server/weapons/weapon_core.qc
|
||||
|
||||
../source/server/entities/powerups.qc
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
../source/server/entities/machines.qc
|
||||
|
||||
../source/server/weapons/frames_core.qc
|
||||
../source/server/weapons/ray_gun.qc
|
||||
../source/server/weapons/weapon_core.qc
|
||||
../source/server/entities/powerups.qc
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
../source/server/entities/machines.qc
|
||||
|
||||
../source/server/weapons/frames_core.qc
|
||||
../source/server/weapons/ray_gun.qc
|
||||
../source/server/weapons/weapon_core.qc
|
||||
../source/server/entities/powerups.qc
|
||||
|
||||
|
|
189
source/server/weapons/ray_gun.qc
Normal file
189
source/server/weapons/ray_gun.qc
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
server/weapons/ray_gun.qc
|
||||
|
||||
Core logic for the Ray Gun special weapon.
|
||||
Modified from Unofficial Patch implementation.
|
||||
|
||||
Copyright (C) 2021-2022 NZ:P Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
|
||||
*/
|
||||
|
||||
//
|
||||
// Ray_BeamExplode(direct_impact)
|
||||
// Calculates damage values, calls for an explosion, and
|
||||
// plays the light effects for the Ray Beam detonation.
|
||||
// ---
|
||||
// direct_impact: Denotes whether or not the Beam collided
|
||||
// with a Monster or if it hit something else (the world).
|
||||
//
|
||||
void(float direct_impact) Ray_BeamExplode =
|
||||
{
|
||||
float raybeam_damage_min;
|
||||
float raybeam_damage_max;
|
||||
float raybeam_damage_radius = 64;
|
||||
|
||||
// Direct shots to the Zombie always deals the same
|
||||
// amount of damage, regardless of PaP status.
|
||||
if (direct_impact == true) {
|
||||
raybeam_damage_min = 1000;
|
||||
raybeam_damage_max = 1000;
|
||||
} else if (IsPapWeapon(self.weapon)) {
|
||||
raybeam_damage_min = 300;
|
||||
raybeam_damage_max = 2000;
|
||||
} else {
|
||||
raybeam_damage_min = 300;
|
||||
raybeam_damage_max = 1800;
|
||||
}
|
||||
|
||||
// Apply the Damage.
|
||||
DamgageExplode(self, self.owner, raybeam_damage_max,
|
||||
raybeam_damage_min, raybeam_damage_radius);
|
||||
|
||||
// Spawn Effects
|
||||
#ifdef PC
|
||||
// Determine color of the beam
|
||||
vector raybeam_color;
|
||||
|
||||
if (IsPapWeapon(self.weapon)) raybeam_color = '1 0 0';
|
||||
else raybeam_color = '0 1 0';
|
||||
|
||||
te_customflash(self.origin, raybeam_damage_radius, 300,
|
||||
raybeam_color);
|
||||
#else
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
#ifdef HANDHELD
|
||||
if (self.effects & EF_RAYGREEN)
|
||||
WriteByte (MSG_BROADCAST, TE_RAYSPLASHGREEN);
|
||||
else
|
||||
WriteByte (MSG_BROADCAST, TE_RAYSPLASHRED);
|
||||
#else
|
||||
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
|
||||
#endif // HANDHELD
|
||||
WriteCoord (MSG_BROADCAST, self.origin_x);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_y);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_z);
|
||||
#endif // PC
|
||||
|
||||
// Cleanup
|
||||
SUB_Remove ();
|
||||
};
|
||||
|
||||
//
|
||||
// Ray_VelocityIncrease()
|
||||
// Constant think function to speed up the Beam gradually.
|
||||
//
|
||||
void() Ray_VelocityIncrease =
|
||||
{
|
||||
self.velocity *= 1.5;
|
||||
self.nextthink = time + 0.1;
|
||||
}
|
||||
|
||||
//
|
||||
// Ray_Impact()
|
||||
// When something touches the Beam, check it's validity for
|
||||
// being used to set up the explosion.
|
||||
//
|
||||
void() Ray_Impact =
|
||||
{
|
||||
if (!other.solid || other.solid == SOLID_TRIGGER)
|
||||
if (other != world)
|
||||
return;
|
||||
|
||||
if (other == self.owner)
|
||||
return;
|
||||
|
||||
float direct_impact;
|
||||
|
||||
if (other.flags & FL_MONSTER)
|
||||
direct_impact = true;
|
||||
else
|
||||
direct_impact = false;
|
||||
|
||||
Ray_BeamExplode(direct_impact);
|
||||
};
|
||||
|
||||
//
|
||||
// W_FireRay()
|
||||
// Called by weapon_core for the Ray firetype. Sets up the
|
||||
// beam/missile and prepares it for impact and force forward.
|
||||
//
|
||||
void() W_FireRay =
|
||||
{
|
||||
// Initially define the beam.
|
||||
entity porter;
|
||||
porter = spawn();
|
||||
porter.owner = self;
|
||||
porter.movetype = MOVETYPE_FLY;
|
||||
porter.weapon = self.weapon;
|
||||
porter.solid = SOLID_BBOX;
|
||||
|
||||
// Start initial velocity projection.
|
||||
makevectors(self.v_angle);
|
||||
porter.velocity = v_forward*2000;
|
||||
porter.avelocity = '0 0 0';
|
||||
|
||||
// Make sure our angle is always FORWARD
|
||||
porter.angles = vectoangles(porter.velocity);
|
||||
porter.angles_z += (porter.angles_z + 180 < 360)? 180 : -180;
|
||||
porter.angles = vectoangles(v_forward);
|
||||
porter.v_angle = '0 0 200';
|
||||
|
||||
// Prepare for Impact and Force forward.
|
||||
porter.touch = Ray_Impact;
|
||||
porter.think = Ray_VelocityIncrease;
|
||||
porter.nextthink = time + 0.1;
|
||||
|
||||
// Set model.
|
||||
setmodel(porter, "models/misc/raybeam.mdl");
|
||||
setsize(porter, '0 0 0', '0 0 0');
|
||||
|
||||
// Prepare trail effects.
|
||||
if (IsPapWeapon(porter.weapon)) {
|
||||
#ifdef HANDHELD
|
||||
porter.effects = EF_RAYRED;
|
||||
#endif // HANDHELD
|
||||
#ifdef QUAKESPASM
|
||||
porter.effects = EF_RED;
|
||||
#endif // QUAKESPASM
|
||||
#ifdef PC
|
||||
Light_Custom(porter, false, 75, 2, 0.25, 0.25);
|
||||
#endif // PC
|
||||
} else {
|
||||
#ifdef HANDHELD
|
||||
porter.effects = EF_RAYGREEN;
|
||||
#endif // HANDHELD
|
||||
#ifdef QUAKESPASM
|
||||
porter.effects = EF_GREEN;
|
||||
#endif // QUAKESPASM
|
||||
#ifdef PC
|
||||
Light_Custom(porter, false, 75, 0.25, 2, 0.25);
|
||||
#endif // PC
|
||||
}
|
||||
|
||||
// final setup!
|
||||
porter.origin = self.origin + self.view_ofs;
|
||||
porter.origin += v_forward * 0;
|
||||
setorigin(porter, porter.origin);
|
||||
|
||||
self.animend = ReturnWeaponModel;
|
||||
self.callfuncat = 0;
|
||||
}
|
|
@ -1072,103 +1072,6 @@ void(float side) W_FireGrenade =
|
|||
setorigin(nade, nade.origin);
|
||||
}
|
||||
|
||||
//
|
||||
// RAY GUN - modified from patch <3
|
||||
//
|
||||
|
||||
void() RayBulletExplode =
|
||||
{
|
||||
DamgageExplode (self, self.owner, 1800, 1800, 64);//we want A SMALL radius of explosion
|
||||
|
||||
// MOTO - FTE explosions are.. large, let's flash instead.
|
||||
|
||||
#ifdef PC
|
||||
te_smallflash(self.origin);
|
||||
#else
|
||||
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
#ifdef HANDHELD
|
||||
if (self.effects & EF_RAYGREEN)
|
||||
WriteByte (MSG_BROADCAST, TE_RAYSPLASHGREEN);
|
||||
else
|
||||
WriteByte (MSG_BROADCAST, TE_RAYSPLASHRED);
|
||||
#else
|
||||
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
|
||||
#endif
|
||||
WriteCoord (MSG_BROADCAST, self.origin_x);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_y);
|
||||
WriteCoord (MSG_BROADCAST, self.origin_z);
|
||||
#endif
|
||||
|
||||
SUB_Remove ();
|
||||
};
|
||||
|
||||
void() velocity_increase_ray =
|
||||
{
|
||||
if (!other.solid || other.solid == SOLID_TRIGGER)
|
||||
if (other != world)
|
||||
return;
|
||||
|
||||
if (other == self.owner)
|
||||
return;
|
||||
|
||||
if (other.solid == SOLID_NOT) {
|
||||
RayBulletExplode();
|
||||
}
|
||||
|
||||
self.velocity = self.velocity*1.5;
|
||||
|
||||
RayBulletExplode();
|
||||
};
|
||||
|
||||
void() W_FireRay =
|
||||
{
|
||||
local entity porter;
|
||||
|
||||
porter = spawn();
|
||||
porter.owner = self;
|
||||
porter.movetype = MOVETYPE_FLY;
|
||||
porter.solid = SOLID_BBOX;
|
||||
|
||||
makevectors(self.v_angle);
|
||||
|
||||
porter.velocity = v_forward*2000;
|
||||
porter.avelocity = '0 0 0';
|
||||
|
||||
porter.angles = vectoangles(porter.velocity);
|
||||
porter.angles_z += (porter.angles_z + 180 < 360)? 180 : -180;
|
||||
porter.angles = vectoangles(v_forward);
|
||||
|
||||
porter.v_angle = '0 0 200';
|
||||
|
||||
porter.touch = velocity_increase_ray;
|
||||
setmodel(porter, "models/misc/raybeam.mdl");
|
||||
setsize(porter, '0 0 0', '0 0 0');
|
||||
|
||||
|
||||
if (self.weapon == W_PORTER) {
|
||||
#ifdef HANDHELD
|
||||
porter.effects = EF_RAYRED;
|
||||
#else
|
||||
porter.effects = EF_RED;
|
||||
#endif
|
||||
} else {
|
||||
#ifdef HANDHELD
|
||||
porter.effects = EF_RAYGREEN;
|
||||
#else
|
||||
porter.effects = EF_GREEN;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
porter.origin = self.origin + self.view_ofs;
|
||||
porter.origin += v_forward * 0;
|
||||
|
||||
setorigin(porter, porter.origin);
|
||||
|
||||
self.animend = ReturnWeaponModel;
|
||||
self.callfuncat = 0;
|
||||
}
|
||||
|
||||
// Remove zombie, add money, request clone spawn.
|
||||
void(entity hit_ent) LightningHit =
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue