#ifdef GAMEQC
REPLICATE(cvar_cl_nade_type, int, "cl_nade_type");
REPLICATE(cvar_cl_pokenade_type, string, "cl_pokenade_type");
+REPLICATE(cvar_cl_tandemnade_type, int, "cl_tandemnade_type");
entity Nade_TrailEffect(int proj, int nade_team)
{
M_ARGV(1, float) = STAT(VEIL_ORB_ALPHA);
return true;
}
+ if (STAT(AMMUNITIONING_ORB) > time) //LegendGuard adds new nade STAT ORB (keep in mind: qcsrc/common/stats.qh) 13-02-2021
+ {
+ M_ARGV(0, vector) = NADE_TYPE_AMMO.m_color;
+ M_ARGV(1, float) = STAT(AMMUNITIONING_ORB_ALPHA);
+ return true;
+ }
+ if (STAT(DARK_ORB) > time) //LegendGuard adds new nade STAT ORB (keep in mind: qcsrc/common/stats.qh) 08-02-2021
+ {
+ M_ARGV(0, vector) = NADE_TYPE_DARK.m_color;
+ M_ARGV(1, float) = STAT(DARK_ORB_ALPHA);
+ return true;
+ }
return false;
}
MUTATOR_HOOKFUNCTION(cl_nades, Ent_Projectile)
#include <common/gamemodes/_mod.qh>
#include <common/monsters/sv_spawn.qh>
#include <common/monsters/sv_monsters.qh>
+//LegendGuard adds include for spawning vehicles 20-06-2021
+#include <common/vehicles/all.qh>
+//LegendGuard adds include for spawning turrets 22-06-2021
+#include <common/turrets/all.qh>
.float nade_time_primed;
.float nade_lifetime;
{
float maxhealth;
float health_factor;
- if(IS_PLAYER(toucher) || IS_MONSTER(toucher))
+ if(IS_PLAYER(toucher) || IS_MONSTER(toucher) || IS_VEHICLE(toucher))
if(!IS_DEAD(toucher))
if(!STAT(FROZEN, toucher))
{
settouch(orb, nade_veil_touch);
orb.colormod = NADE_TYPE_VEIL.m_color;
}
+/**************LEGENDGUARD NEW NADES: EMERALD, AMMO AND DARK NADES functions "cl_nade_type 10", "cl_nade_type 11" and "cl_nade_type 12" *** //more ideas: SPAWNING MINI SPIDERS NADE, SPARKING NADE ***********************/
+// All nade icons are in these directories, samples: gfx/hud/default/nade_emerald.tga and gfx/hud/luma/nade_emerald.tga 02-03-2021
+// Mario suggests to rename itemdrop nade name to "emerald" nade 02-03-2021
+void nade_emerald_dropitem(entity e, vector org, entity itm)
+{
+ Item_SetLoot(e, true);
+ e.reset = SUB_Remove;
+ e.noalign = true;
+ StartItem(e, itm);
+ e.gravity = 1;
+ setorigin(e, org);
+ e.velocity = randomvec() * 175 + '0 0 325';
+ e.item_spawnshieldtime = time + 0.7;
+ SUB_SetFade(e, time + autocvar_g_nades_emerald_lifetime, 1);
+ Send_Effect(EFFECT_SMOKE_LARGE, e.origin, '0 0 0', 1);
+ //EFFECT_SMOKE_LARGE is like a small white smoke
+ //See effect MACROS in qcsrc/common/effects/all.inc
+}
+
+//LegendGuard adds weapon item spawn option for emerald nade 25-05-2021
+void nade_emerald_SpawnWeapon(entity ent, vector org, entity wep)
+{
+ Item_SetLoot(ent, true);
+ ent.pickup_anyway = true;
+ ent.angles = '0 0 0';
+ ent.gravity = 1;
+ setorigin(ent, org);
+ ent.velocity = randomvec() * 150 + '0 0 325';
+ ent.spawnfunc_checked = true;
+ ent.glowmod = weaponentity_glowmod(wep, ent, 0, NULL);
+ weapon_defaultspawnfunc(ent, wep);
+ // fading handled globally
+}
+
+//LegendGuard adds random weapon item spawn function for emerald nade 25-05-2021
+void nade_emerald_randomweapons(entity e, vector org)
+{
+ if (random() > 0.5)
+ {
+ RandomSelection_Init();
+ FOREACH(Weapons, it != WEP_Null && (!((it.spawnflags & WEP_FLAG_HIDDEN) || (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)) || autocvar_g_nades_emerald_randomweapons_includespecial),
+ {
+ if((it.spawnflags & WEP_FLAG_HIDDEN) && (it.spawnflags & WEP_FLAG_MUTATORBLOCKED))
+ continue;
+ float chancewep = 1;
+ if(it.spawnflags & WEP_FLAG_SPECIALATTACK) //LegendGuard fixes the strange part of the code
+ chancewep = 0;
+ if (W_IsWeaponThrowable(e, it.m_id))
+ RandomSelection_AddEnt(it, chancewep, 1);
+ });
+ nade_emerald_SpawnWeapon(e, org, RandomSelection_chosen_ent);
+ }
+ else
+ return;
+}
+
+//LegendGuard adds vehicle spawn option for emerald nade 20-06-2021
+void nade_emerald_SpawnVehicle(entity ent, vector org, entity veh)
+{
+ ent.noalign = true; // don't drop to floor
+ ent.angles = '0 0 0';
+ ent.gravity = 1;
+ setorigin(ent, org);
+ ent.velocity = randomvec() * 150 + '0 0 325';
+ ent.spawnfunc_checked = true;
+ time = 0.5;
+ vehicle_initialize(ent, veh, 1);
+}
+
+//LegendGuard adds random vehicle spawn selection function for emerald nade 20-06-2021
+void nade_emerald_randomvehicles(entity e, vector org)
+{
+ RandomSelection_Init();
+ FOREACH(Vehicles, it != VEH_Null && (!((it.spawnflags & VHF_MULTISLOT))),
+ {
+ if(it.spawnflags & VHF_MULTISLOT || it.classname == "Bumblebee") //No Bumblebee, please
+ continue;
+ float chanceveh = 1;
+ if(it.spawnflags & VHF_MOVE_FLY)
+ chanceveh = 0;
+ RandomSelection_AddEnt(it, chanceveh, 1);
+ });
+ nade_emerald_SpawnVehicle(e, org, RandomSelection_chosen_ent);
+}
+
+//LegendGuard adds turret spawn option for emerald nade 22-06-2021
+//EXPERIMENTAL
+//TODO: turrets must be spawned by owner team, cannot be spawned to attack owner team or both
+void nade_emerald_SpawnTurret(entity ent, vector org, entity tur)
+{
+ //FOREACH_CLIENT(IS_PLAYER(it),
+ //{
+ if (ent.turspawncount < autocvar_g_nades_emerald_turretspawnlimit)
+ {
+ //ent = spawn();
+ //ent.owner = it.owner;
+ //ent.realowner = it.realowner;
+ //ent.team = ent.realowner.team;
+ //FOREACH_CLIENT(!IS_OBSERVER(it.realowner), ent.team = it.team;);
+ ent.noalign = true; // don't drop to floor
+ //ent.angles = '0 0 0';
+ //ent.gravity = 1;
+ setorigin(ent, org);
+ //ent.velocity = randomvec() * 150 + '0 0 325';
+ ent.spawnfunc_checked = true;
+ //ent.solid = SOLID_CORPSE;
+ //setthink(ent, turrets_respawn);
+ // fading handled globally
+ //bool turret_initialize(entity this, Turret tur)
+ //turret_validate_target(ent.realowner, ent.enemy, ent.target_validate_flags);
+ turret_initialize(ent, tur);
+ //it.turspawncount++;
+ //PrintToChatAll(sprintf("^1AFTER^7 it.turspawncount: ^3%f", it.turspawncount));
+ //if (!IS_ONGROUND(ent))
+ // ent.gravity = 1; setorigin(ent, org);
+ }
+ else
+ {
+ //centerprint(it, strcat(BOLD_OPERATOR, "^1You cannot spawn more turrets!"));
+ PrintToChatAll("^1Someone tried to spawn more turrets than the maximum allowed! Sorry, cannot be spawned, spawn limit has been reached!");
+ }
+ //PrintToChatAll(sprintf("^4tur- ^2it.netname: %s", it.netname));
+ //PrintToChatAll(sprintf("^4tur- ^1tur.classname: %s", tur.classname));
+ // return;
+ //});
+}
+
+//LegendGuard adds random turret spawn function for emerald nade 22-06-2021
+//EXPERIMENTAL
+void nade_emerald_randomturrets(entity e, vector org)
+{
+ /*//taken from: qcsrc/common/turrets/turret.qh
+ const int TSF_SUSPENDED = 1;
+ const int TSF_TERRAINBASE = 2; // currently unused
+ const int TSF_NO_AMMO_REGEN = 4; // disable builtin ammo regeneration
+ const int TSF_NO_PATHBREAK = 8; // don't break path to chase enemies, will still fire at them if possible
+ const int TSL_NO_RESPAWN = 16; // don't re-spawn
+ const int TSL_ROAM = 32; // roam while idle*/
+ RandomSelection_Init();
+ FOREACH(Turrets, it != TUR_Null && (!((it.spawnflags & TSF_SUSPENDED))),
+ {
+ if(it.spawnflags & TSF_SUSPENDED)
+ continue;
+ float chancetur = 1;
+ if(it.spawnflags & TSF_NO_PATHBREAK)
+ chancetur = 0;
+ RandomSelection_AddEnt(it, chancetur, 1);
+ });
+ nade_emerald_SpawnTurret(e, org, RandomSelection_chosen_ent);
+}
+
+void nade_emerald_randomitem(entity e, vector org)
+{
+ float a = random();
+ float b = random();
+ float c = random();
+ float d = random();
+
+ if (a > b)
+ {
+ if (a > 0.5)
+ nade_emerald_dropitem(e, org, ((random() > 0.5) ? ITEM_ArmorSmall : ITEM_HealthSmall));
+ else if (d < 0.2)
+ nade_emerald_dropitem(e, org, ((random() > 0.5) ? ITEM_Shells : ITEM_Bullets));
+ }
+ else if (c > d)
+ {
+ if (c > 0.5)
+ nade_emerald_dropitem(e, org, ((random() > 0.5) ? ITEM_Rockets : ITEM_Cells));
+ else if (b < 0.2)
+ nade_emerald_dropitem(e, org, ((random() > 0.5) ? ITEM_Cells : ITEM_Shells));
+ }
+ else if (autocvar_g_nades_emerald_powerupjetpack_randomdrop)
+ {
+ if (a < 0.5)
+ nade_emerald_dropitem(e, org, ((random() > 0.5) ? ITEM_Jetpack : ITEM_JetpackFuel));
+ else if (c < 0.5)
+ nade_emerald_dropitem(e, org, ((random() > 0.5) ? ITEM_Shield : ITEM_Strength));
+ else
+ {
+ if(IS_GAMETYPE(FREEZETAG) || IS_GAMETYPE(LMS))
+ nade_emerald_dropitem(e, org, ((random() > 0.5) ? ITEM_ArmorSmall : ITEM_HealthSmall));
+ else
+ nade_emerald_randomweapons(e, org);
+ }
+ }
+ else
+ {
+ if (a > 0.5)
+ nade_emerald_dropitem(e, org, ((random() > 0.5) ? ITEM_ArmorSmall : ITEM_HealthSmall));
+ else if (d < 0.2)
+ nade_emerald_dropitem(e, org, ((random() > 0.5) ? ITEM_Shells : ITEM_Rockets));
+ else
+ {
+ if(IS_GAMETYPE(FREEZETAG) || IS_GAMETYPE(LMS))
+ nade_emerald_dropitem(e, org, ((random() > 0.5) ? ITEM_ArmorSmall : ITEM_HealthSmall));
+ else
+ nade_emerald_randomweapons(e, org);
+ }
+ return;
+ }
+}
+
+void nade_emerald_allammoitemdrop(entity e, vector org)
+{
+ float wa = random();
+ float wb = random();
+
+ if (wa > wb)
+ {
+ if (wa > 0.5)
+ nade_emerald_dropitem(e, org, ((random() > 0.5) ? ITEM_Shells : ITEM_Bullets));
+ else
+ nade_emerald_dropitem(e, org, ((random() > 0.5) ? ITEM_Rockets : ITEM_Cells));
+ }
+ else
+ return;
+}
+
+void nade_emerald_dropping(vector org)
+{
+ //look item MACROS in qcsrc/server/items/items.qc
+ //ITEM_Shells; ITEM_Bullets; ITEM_Rockets; ITEM_Cells; ITEM_Plasma; ITEM_JetpackFuel;
+ //ITEM_Strength; ITEM_Shield;
+ int itemcount = autocvar_g_nades_emerald_spawncount;
+ entity e = spawn();
+ e.spawnfunc_checked = true;
+ if(!IS_GAMETYPE(CA) && !autocvar_g_instagib)
+ {
+ //int cvar which manages the ONLY dropping per each type of item 14-03-2021
+ switch (autocvar_g_nades_emerald_dropitemselect)
+ {
+ case 0: for(int j = 0; j < itemcount; ++j){ nade_emerald_randomitem(e, org); return;}
+ case 1: for(int j = 0; j < itemcount; ++j){ nade_emerald_dropitem(e, org, ITEM_HealthSmall); return;}
+ case 2: for(int j = 0; j < itemcount; ++j){ nade_emerald_dropitem(e, org, ITEM_ArmorSmall); return;}
+ case 3: for(int j = 0; j < itemcount; ++j){ nade_emerald_allammoitemdrop(e, org); return;}
+ case 4: for(int j = 0; j < itemcount; ++j){ nade_emerald_dropitem(e, org, ITEM_Shells); return;}
+ case 5: for(int j = 0; j < itemcount; ++j){ nade_emerald_dropitem(e, org, ITEM_Bullets); return;}
+ case 6: for(int j = 0; j < itemcount; ++j){ nade_emerald_dropitem(e, org, ITEM_Rockets); return;}
+ case 7: for(int j = 0; j < itemcount; ++j){ nade_emerald_dropitem(e, org, ITEM_Cells); return;}
+ case 8: for(int j = 0; j < itemcount; ++j){ nade_emerald_dropitem(e, org, ITEM_Jetpack); return;}
+ case 9: for(int j = 0; j < itemcount; ++j){ nade_emerald_dropitem(e, org, ITEM_JetpackFuel); return;}
+ case 10: for(int j = 0; j < itemcount; ++j){ nade_emerald_dropitem(e, org, ITEM_Shield); return;}
+ case 11: for(int j = 0; j < itemcount; ++j){ nade_emerald_dropitem(e, org, ITEM_Strength); return;}
+ case 12: for(int j = 0; j < itemcount; ++j){ nade_emerald_randomweapons(e, org); return;}
+ default: for(int j = 0; j < itemcount; ++j){ nade_emerald_randomitem(e, org); return;}
+ }
+ }
+}
+
+void emerald_ball_think(entity this)
+{
+ if(round_handler_IsActive())
+ if(!round_handler_IsRoundStarted())
+ {
+ delete(this);
+ return;
+ }
+
+ if(time > this.pushltime)
+ {
+ delete(this);
+ return;
+ }
+
+ vector midpoint = ((this.absmin + this.absmax) * 0.5);
+ if(pointcontents(midpoint) == CONTENT_WATER)
+ {
+ this.velocity = this.velocity * 0.5;
+
+ if(pointcontents(midpoint + '0 0 16') == CONTENT_WATER)
+ { this.velocity_z = 200; }
+ }
+
+ this.angles = vectoangles(this.velocity);
+
+ nade_emerald_dropping(this.origin);
+
+ this.nextthink = time + 0.1;
+}
+
+void nade_emerald_ball(entity this)
+{
+ entity proj;
+ vector kick;
+
+ spamsound(this, CH_SHOTS, SND_FIREBALL_FIRE, VOL_BASE, ATTEN_NORM);
+
+ proj = new(grenade);
+ proj.bot_dodge = true;
+ set_movetype(proj, MOVETYPE_BOUNCE);
+ setmodel(proj, MDL_Null);
+ proj.scale = 1;//0.5;
+ setsize(proj, '-4 -4 -4', '4 4 4');
+ setorigin(proj, this.origin);
+ setthink(proj, emerald_ball_think);
+ proj.nextthink = time;
+ proj.effects = EF_LOWPRECISION;
+
+ kick.x =(random() - 0.5) * 2 * autocvar_g_nades_emerald_ball_spread;
+ kick.y = (random() - 0.5) * 2 * autocvar_g_nades_emerald_ball_spread;
+ kick.z = (random()/2+0.5) * autocvar_g_nades_emerald_ball_spread;
+ proj.velocity = kick;
+
+ proj.pushltime = time + autocvar_g_nades_emerald_ball_lifetime;
+
+ proj.angles = vectoangles(proj.velocity);
+ proj.flags = FL_PROJECTILE;
+ IL_PUSH(g_projectiles, proj);
+ IL_PUSH(g_bot_dodge, proj);
+ proj.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_ARC;
+
+ //CSQCProjectile(proj, true, PROJECTILE_NAPALM_FIRE, true);
+}
+
+void emerald_fountain_think(entity this)
+{
+ if(round_handler_IsActive())
+ if(!round_handler_IsRoundStarted())
+ {
+ delete(this);
+ return;
+ }
+
+ if(time >= this.ltime)
+ {
+ Send_Effect(EFFECT_SMOKE_SMALL, this.origin + '0 0 1', '0 0 0', 1);
+ sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
+
+ delete(this);
+ return;
+ }
+
+ vector midpoint = ((this.absmin + this.absmax) * 0.5);
+ if(pointcontents(midpoint) == CONTENT_WATER)
+ {
+ this.velocity = this.velocity * 0.5;
+
+ if(pointcontents(midpoint + '0 0 16') == CONTENT_WATER)
+ { this.velocity_z = 200; }
+
+ UpdateCSQCProjectile(this);
+ }
+
+ this.nextthink = time + 0.1;
+ if(time >= this.nade_special_time)
+ {
+ this.nade_special_time = time + autocvar_g_nades_emerald_fountain_delay;
+ nade_emerald_ball(this);
+ }
+}
+
+void nade_emerald_boom(entity this)
+{
+ entity e = spawn();
+ bool spawnlimited = false;
+
+ switch (this.tandemnade_type)
+ {
+ case 1:
+ {
+ FOREACH_CLIENT(IS_PLAYER(it),
+ {
+ if (it.vehspawncount < autocvar_g_nades_emerald_vehiclespawnlimit)
+ {
+ spawnlimited = false;
+ //PrintToChatAll(sprintf("^2BEFORE^7 it.vehspawncount: ^3%f", it.vehspawncount));
+ it.vehspawncount++;
+ //PrintToChatAll(sprintf("^1AFTER^7 it.vehspawncount: ^3%f", it.vehspawncount));
+ }
+ else
+ spawnlimited = true;
+ });
+ if(spawnlimited == true)
+ PrintToChatAll("^1Someone tried to spawn more vehicles than the maximum allowed! Sorry, cannot be spawned, spawn limit has been reached!");
+ else
+ nade_emerald_randomvehicles(e, this.origin);
+
+ return;
+ }
+ case 2: nade_emerald_randomturrets(e, this.origin); return; //EXPERIMENTAL
+ default:
+ {
+ for (int c = 0; c < autocvar_g_nades_emerald_ball_count; c++)
+ nade_emerald_ball(this);
+
+ entity fountain = new(nade_emerald_fountain);
+ fountain.owner = this.owner;
+ fountain.realowner = this.realowner;
+ fountain.origin = this.origin;
+ fountain.flags = FL_PROJECTILE;
+ IL_PUSH(g_projectiles, fountain);
+ IL_PUSH(g_bot_dodge, fountain);
+ setorigin(fountain, fountain.origin);
+ setthink(fountain, emerald_fountain_think);
+ fountain.nextthink = time;
+ fountain.ltime = time + autocvar_g_nades_emerald_fountain_lifetime;
+ fountain.pushltime = fountain.ltime;
+ fountain.team = this.team;
+
+ //nade model maintaining
+ setmodel(fountain, MDL_PROJECTILE_GRENADE);
+ entity timer = new(nade_timer);
+ setmodel(timer, MDL_NADE_TIMER);
+ setattachment(timer, fountain, "");
+ timer.colormap = this.colormap;
+ timer.glowmod = this.glowmod;
+ setthink(timer, nade_timer_think);
+ timer.nextthink = time;
+ timer.wait = fountain.ltime;
+ timer.owner = fountain;
+ timer.skin = 10;
+
+ set_movetype(fountain, MOVETYPE_TOSS);
+ fountain.bot_dodge = true;
+ fountain.nade_special_time = time;
+ setsize(fountain, '-16 -16 -16', '16 16 16');
+ CSQCProjectile(fountain, true, PROJECTILE_NADE_EMERALD_BURN, true);
+ nade_emerald_dropping(fountain.origin);
+ }
+ }
+}
+
+/***********************************************************************************/
+//LegendGuard develops ammo nade 13-02-2021
+void nade_ammo_touch(entity this, entity toucher)
+{
+ float maxammo = 999;
+ float ammo_factor;
+ float amshells = GetResource(toucher, RES_SHELLS);
+ float ambullets = GetResource(toucher, RES_BULLETS);
+ float amrockets = GetResource(toucher, RES_ROCKETS);
+ float amcells = GetResource(toucher, RES_CELLS);
+ float amplasma = GetResource(toucher, RES_PLASMA);
+ if(IS_PLAYER(toucher) || IS_MONSTER(toucher))
+ if(!IS_DEAD(toucher))
+ if(!STAT(FROZEN, toucher))
+ {
+ ammo_factor = autocvar_g_nades_ammo_rate*frametime/2;
+ if ( toucher != this.realowner )
+ {
+ if ( SAME_TEAM(toucher,this) )
+ ammo_factor *= autocvar_g_nades_ammo_friend;
+ else
+ ammo_factor *= autocvar_g_nades_ammo_foe;
+ }
+ if ( ammo_factor > 0 )
+ {
+ if (amshells < maxammo)
+ GiveResourceWithLimit(toucher, RES_SHELLS, ammo_factor, maxammo);
+
+ if (ambullets < maxammo)
+ GiveResourceWithLimit(toucher, RES_BULLETS, ammo_factor, maxammo);
+
+ if (amrockets < maxammo)
+ GiveResourceWithLimit(toucher, RES_ROCKETS, ammo_factor, maxammo);
+
+ if (amcells < maxammo)
+ GiveResourceWithLimit(toucher, RES_CELLS, ammo_factor, maxammo);
+
+ if (amplasma < maxammo)
+ GiveResourceWithLimit(toucher, RES_PLASMA, ammo_factor, maxammo);
+
+ if (this.nade_show_particles)
+ Send_Effect(EFFECT_HEALING, toucher.origin, '0 0 0', 1);
+ }
+ else if ( ammo_factor < 0 )
+ {
+ //Foe drops ammo points
+ if (amshells > 0)
+ SetResource(toucher, RES_SHELLS, amshells + ammo_factor);
+
+ if (ambullets > 0)
+ SetResource(toucher, RES_BULLETS, ambullets + ammo_factor);
+
+ if (amrockets > 0)
+ SetResource(toucher, RES_ROCKETS, amrockets + ammo_factor);
+
+ if (amcells > 0)
+ SetResource(toucher, RES_CELLS, amcells + ammo_factor);
+
+ if (amplasma > 0)
+ SetResource(toucher, RES_PLASMA, amplasma + ammo_factor);
+
+ return;
+ }
+ }
+
+ if ( IS_REAL_CLIENT(toucher) || IS_VEHICLE(toucher) )
+ {
+ entity show_brown = (IS_VEHICLE(toucher)) ? toucher.owner : toucher;
+ STAT(AMMUNITIONING_ORB, show_brown) = time+0.1;
+ STAT(AMMUNITIONING_ORB_ALPHA, show_brown) = 0.75 * (this.ltime - time) / this.orb_lifetime;
+ }
+}
+void nade_ammo_boom(entity this)
+{
+ entity orb = nades_spawn_orb(this.owner, this.realowner, this.origin, autocvar_g_nades_ammo_time, autocvar_g_nades_nade_radius);
+
+ settouch(orb, nade_ammo_touch);
+ orb.colormod = '0.66 0.33 0';
+}
+/***********************************************************************************/
+//remember to put an image in gfx/hud/luma and gfx/hud/default per each nade_blabla.tga
+//dark nade does damage like a normal nade but the damage is minor
+//add Dark smoke effect when exploded 28-02-2021
+void dark_damage(entity this, float radius, float damage)
+{
+ entity e;
+
+ if ( damage < 0 )
+ return;
+
+ for(e = WarpZone_FindRadius(this.origin, radius, true); e; e = e.chain)
+ if(!IS_DEAD(e))
+ if(e.takedamage == DAMAGE_AIM)
+ if(!IS_PLAYER(e) || !this.realowner || DIFF_TEAM(e, this) || !IS_MONSTER(e))
+ if(!STAT(FROZEN, e))
+ {
+ Damage(this, this, this.realowner, damage, DEATH_NADE.m_id, DMG_NOWEP, this.origin, '0 0 0');
+ Damage_DamageInfo(this.origin, damage, autocvar_g_nades_nade_edgedamage,
+ radius, '1 1 1' * 0, DEATH_NADE.m_id, 0, this);
+ }
+}
+
+void nade_dark_fountain_think(entity this)
+{
+ if(round_handler_IsActive())
+ if(!round_handler_IsRoundStarted())
+ {
+ delete(this);
+ return;
+ }
+
+ if(time >= this.ltime)
+ {
+ Send_Effect(EFFECT_SMOKE_SMALL, this.origin + '0 0 1', '0 0 0', 1);
+ delete(this);
+ return;
+ }
+
+ this.nextthink = time + 0.1;
+
+ // gaussian
+ float randomr;
+ randomr = random();
+ randomr = exp(-5*randomr*randomr)*autocvar_g_nades_dark_radius;
+ float randomw;
+ randomw = random()*M_PI*2;
+ vector randomp;
+ randomp.x = randomr*cos(randomw);
+ randomp.y = randomr*sin(randomw);
+ randomp.z = 1;
+ Send_Effect(EFFECT_SMOKE_SMALL, this.origin + randomp, '0 0 0', 1);
+
+ if(time >= this.nade_special_time)
+ {
+ this.nade_special_time = time + 0.7;
+ Send_Effect(EFFECT_SMOKE_SMALL, this.origin, '0 0 0', 1);
+ }
+}
+
+void DarkBlinking(entity e);
+//copy of the special.qc function contents for DarkBlinking
+void nade_dark_touch(entity this, entity toucher)
+{
+ if ( IS_REAL_CLIENT(toucher) || IS_VEHICLE(toucher) || IS_MONSTER(toucher) )
+ {
+ entity show_tint = (IS_VEHICLE(toucher)) ? toucher.owner : toucher;
+
+ float tint_alpha = 0.75;
+ if(SAME_TEAM(toucher, this.realowner) || SAME_TEAM(toucher, this))
+ {
+ tint_alpha = 0.45;
+ if(!STAT(DARK_ORB, show_tint))
+ {
+ toucher.nade_dark_prevalpha = toucher.alpha;
+ toucher.alpha = 1;
+ }
+ }
+ else
+ {
+ tint_alpha = 0.45;
+ if(!STAT(DARK_ORB, show_tint))
+ {
+ DarkBlinking(toucher);
+ dark_damage(toucher, autocvar_g_nades_dark_radius, autocvar_g_nades_dark_damage);
+ }
+ }
+
+ STAT(DARK_ORB, show_tint) = time + 0.1;
+ STAT(DARK_ORB_ALPHA, show_tint) = tint_alpha * (this.ltime - time) / this.orb_lifetime;
+ }
+}
+
+void nade_dark_boom(entity this)
+{
+ entity orb = nades_spawn_orb(this.owner, this.realowner, this.origin, autocvar_g_nades_dark_time, autocvar_g_nades_dark_radius);
+ entity fountain = new(nade_dark_fountain);
+
+ fountain.owner = this.owner;
+ fountain.realowner = this.realowner;
+ fountain.origin = this.origin;
+ fountain.flags = FL_PROJECTILE;
+ IL_PUSH(g_projectiles, fountain);
+ IL_PUSH(g_bot_dodge, fountain);
+ setorigin(fountain, fountain.origin);
+ setthink(fountain, nade_dark_fountain_think);
+ fountain.nextthink = time;
+ fountain.ltime = time + autocvar_g_nades_dark_time;
+ fountain.pushltime = fountain.wait = fountain.ltime;
+ fountain.team = this.team;
+ fountain.bot_dodge = false;
+ setsize(fountain, '-16 -16 -16', '16 16 16');
+ fountain.nade_special_time = time + 0.3;
+ fountain.angles = this.angles;
+
+ settouch(orb, nade_dark_touch);
+ orb.colormod = NADE_TYPE_DARK.m_color;
+ //CSQCProjectile(fountain, true, PROJECTILE_NADE_DARK_BURN, true);
+}
+/***********************************************************************************/
void nade_boom(entity this)
{
entity expef = NULL;
nade_blast = false;
expef = EFFECT_SPAWN_NEUTRAL;
break;
+
+ case NADE_TYPE_EMERALD: //LegendGuard adds nade case 11-02-2021
+ nade_blast = false;
+ expef = EFFECT_EXPLOSION_SMALL;
+ break;
+
+ case NADE_TYPE_AMMO: //LegendGuard adds nade case 13-02-2021
+ nade_blast = false;
+ expef = EFFECT_SPAWN_BROWN;
+ break;
+
+ case NADE_TYPE_DARK: //LegendGuard adds nade case 08-02-2021
+ nade_blast = false;
+ expef = EFFECT_EXPLOSION_MEDIUM;
+ break;
default:
case NADE_TYPE_NORMAL:
case NADE_TYPE_MONSTER: nade_monster_boom(this); break;
case NADE_TYPE_ENTRAP: nade_entrap_boom(this); break;
case NADE_TYPE_VEIL: nade_veil_boom(this); break;
+ case NADE_TYPE_EMERALD: nade_emerald_boom(this); break; //LegendGuard adds the register of new nade 11-02-2021
+ case NADE_TYPE_AMMO: nade_ammo_boom(this); break; //LegendGuard adds the register of new nade 13-02-2021
+ case NADE_TYPE_DARK: nade_dark_boom(this); break; //LegendGuard adds the register of new nade 08-02-2021
}
IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this,
delete(this);
}
-void spawn_held_nade(entity player, entity nowner, float ntime, int ntype, string pntype);
+void spawn_held_nade(entity player, entity nowner, float ntime, int ntype, string pntype, int tntype);
void nade_pickup(entity this, entity thenade)
{
- spawn_held_nade(this, thenade.realowner, autocvar_g_nades_pickup_time, STAT(NADE_BONUS_TYPE, thenade), thenade.pokenade_type);
+ spawn_held_nade(this, thenade.realowner, autocvar_g_nades_pickup_time, STAT(NADE_BONUS_TYPE, thenade), thenade.pokenade_type, thenade.tandemnade_type);
// set refire so player can't even
this.nade_refire = time + autocvar_g_nades_nade_refire;
return true;
}
-void spawn_held_nade(entity player, entity nowner, float ntime, int ntype, string pntype)
+void spawn_held_nade(entity player, entity nowner, float ntime, int ntype, string pntype, int tntype)
{
entity n = new(nade), fn = new(fake_nade);
STAT(NADE_BONUS_TYPE, n) = max(1, ntype);
n.pokenade_type = pntype;
+ n.tandemnade_type = tntype;
if(REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, n)) == NADE_TYPE_Null)
STAT(NADE_BONUS_TYPE, n) = NADE_TYPE_NORMAL.m_id;
this.fake_nade = NULL;
int ntype;
+ int tntype = this.tandemnade_type;
string pntype = this.pokenade_type;
if(StatusEffects_active(STATUSEFFECT_Strength, this) && autocvar_g_nades_bonus_onstrength)
{
ntype = STAT(NADE_BONUS_TYPE, this);
pntype = this.pokenade_type;
+ tntype = this.tandemnade_type;
STAT(NADE_BONUS, this) -= 1;
}
else
{
ntype = ((autocvar_g_nades_client_select) ? CS_CVAR(this).cvar_cl_nade_type : autocvar_g_nades_nade_type);
pntype = ((autocvar_g_nades_client_select) ? CS_CVAR(this).cvar_cl_pokenade_type : autocvar_g_nades_pokenade_monster_type);
+ tntype = ((autocvar_g_nades_client_select) ? CS_CVAR(this).cvar_cl_tandemnade_type : autocvar_g_nades_tandemnade_type);
}
- spawn_held_nade(this, this, autocvar_g_nades_nade_lifetime, ntype, pntype);
+ spawn_held_nade(this, this, autocvar_g_nades_nade_lifetime, ntype, pntype, tntype);
}
bool CanThrowNade(entity this)
{
STAT(NADE_BONUS_TYPE, player) = CS_CVAR(player).cvar_cl_nade_type;
player.pokenade_type = CS_CVAR(player).cvar_cl_pokenade_type;
+ player.tandemnade_type = CS_CVAR(player).cvar_cl_tandemnade_type;
}
else
{
STAT(NADE_BONUS_TYPE, player) = autocvar_g_nades_bonus_type;
player.pokenade_type = autocvar_g_nades_pokenade_monster_type;
+ player.tandemnade_type = autocvar_g_nades_tandemnade_type;
}
STAT(NADE_BONUS_TYPE, player) = bound(1, STAT(NADE_BONUS_TYPE, player), Nades_COUNT);
else
player.alpha = player.nade_veil_prevalpha;
}
+ //LegendGuard adds nade if STAT DARK_ORB 08-02-2021
+ if(STAT(DARK_ORB, player) && STAT(DARK_ORB, player) <= time)
+ {
+ STAT(DARK_ORB, player) = 0;
+ if(player.vehicle)
+ player.vehicle.alpha = player.vehicle.nade_dark_prevalpha;
+ else
+ player.alpha = player.nade_dark_prevalpha;
+ }
}
if (!(frametime && IS_PLAYER(player)))
mon.alpha = mon.nade_veil_prevalpha;
STAT(VEIL_ORB, mon) = 0;
}
+ //LegendGuard adds nade if STAT ORB 08-02-2021
+ if (STAT(DARK_ORB, mon) && STAT(DARK_ORB, mon) <= time)
+ {
+ mon.alpha = mon.nade_dark_prevalpha;
+ STAT(DARK_ORB, mon) = 0;
+ }
}
MUTATOR_HOOKFUNCTION(nades, PlayerSpawn)
STAT(NADE_TIMER, client) = STAT(NADE_TIMER, spectatee);
STAT(NADE_BONUS_TYPE, client) = STAT(NADE_BONUS_TYPE, spectatee);
client.pokenade_type = spectatee.pokenade_type;
+ client.tandemnade_type = spectatee.tandemnade_type;
STAT(NADE_BONUS, client) = STAT(NADE_BONUS, spectatee);
STAT(NADE_BONUS_SCORE, client) = STAT(NADE_BONUS_SCORE, spectatee);
STAT(HEALING_ORB, client) = STAT(HEALING_ORB, spectatee);
STAT(ENTRAP_ORB_ALPHA, client) = STAT(ENTRAP_ORB_ALPHA, spectatee);
STAT(VEIL_ORB, client) = STAT(VEIL_ORB, spectatee);
STAT(VEIL_ORB_ALPHA, client) = STAT(VEIL_ORB_ALPHA, spectatee);
+ STAT(AMMUNITIONING_ORB, client) = STAT(AMMUNITIONING_ORB, spectatee); //LegendGuard adds nade STAT client 13-02-2021
+ STAT(AMMUNITIONING_ORB_ALPHA, client) = STAT(AMMUNITIONING_ORB_ALPHA, spectatee);
+ STAT(DARK_ORB, client) = STAT(DARK_ORB, spectatee); //LegendGuard adds nade STAT client 08-02-2021
+ STAT(DARK_ORB_ALPHA, client) = STAT(DARK_ORB_ALPHA, spectatee);
}
MUTATOR_HOOKFUNCTION(nades, BuildMutatorsString)
float autocvar_g_nades_entrap_time = 10;
float autocvar_g_nades_veil_time = 8;
float autocvar_g_nades_veil_radius = 300;
+float autocvar_g_nades_emerald_lifetime = 5; //LegendGuard adds new nade cvars 28-02-2021
+bool autocvar_g_nades_emerald_randomweapons_includespecial = false;
+float autocvar_g_nades_emerald_spawncount = 1;
+float autocvar_g_nades_emerald_ball_spread = 0.5;
+float autocvar_g_nades_emerald_ball_lifetime = 1; //if much time, many items will spawn
+float autocvar_g_nades_emerald_fountain_delay = 5;
+float autocvar_g_nades_emerald_ball_count = 3;
+float autocvar_g_nades_emerald_fountain_lifetime = 1; //if much time, fountain will remain
+bool autocvar_g_nades_emerald_powerupjetpack_randomdrop = 0;
+int autocvar_g_nades_emerald_dropitemselect = 0; //admin/user selects which item wants to drop in-game, if not will be random
+int autocvar_g_nades_emerald_vehiclespawnlimit = 6; //LegendGuard adds new nade cvar of vehicle spawn count limit for the server 26-06-2021
+int autocvar_g_nades_emerald_turretspawnlimit = 4; // EXPERIMENTAL 26-06-2021
+float autocvar_g_nades_ammo_time = 5; //LegendGuard adds new nade cvars 13-02-2021
+float autocvar_g_nades_ammo_rate = 30;
+float autocvar_g_nades_ammo_friend = 1;
+float autocvar_g_nades_ammo_foe = -2;
+float autocvar_g_nades_dark_damage = 25; //LegendGuard adds new nade cvars 08-02-2021
+float autocvar_g_nades_dark_time = 13;
+float autocvar_g_nades_dark_radius = 700;
string autocvar_g_nades_pokenade_monster_type;
+int autocvar_g_nades_tandemnade_type; //LegendGuard adds new nade cvar for emerald nade options 01-07-2021
float autocvar_g_nades_pokenade_monster_lifetime;
#endif
const int PROJECTILE_NADE_ENTRAP_BURN = 85;
const int PROJECTILE_NADE_VEIL = 86;
const int PROJECTILE_NADE_VEIL_BURN = 87;
+const int PROJECTILE_NADE_EMERALD = 88; //LegendGuard adds new nade MACROS 11-02-2021
+const int PROJECTILE_NADE_EMERALD_BURN = 89;
+const int PROJECTILE_NADE_AMMO = 90; //LegendGuard adds new nade MACROS 13-02-2021
+const int PROJECTILE_NADE_AMMO_BURN = 91;
+const int PROJECTILE_NADE_DARK = 92; //LegendGuard adds new nade MACROS 08-02-2021
+const int PROJECTILE_NADE_DARK_BURN = 93;
REGISTRY(Nades, BITS(4))
REGISTER_REGISTRY(Nades)
.float nade_refire;
.float nade_special_time;
.string pokenade_type;
+.float tandemnade_type; //LegendGuard adds new cvar nade .variable 01-07-2021
.entity nade_damage_target;
.float cvar_cl_nade_type;
.string cvar_cl_pokenade_type;
+.int cvar_cl_tandemnade_type; //LegendGuard adds new cvar nade .variable 01-07-2021
.float toss_time;
.float nade_show_particles;
.float nade_veil_prevalpha;
+.float nade_dark_prevalpha; //LegendGuard adds new nade .variable 08-02-2021
+.int vehspawncount; //LegendGuard adds new .variable 22-06-2021
+.int turspawncount; //EXPERIMENTAL 26-06-2021
bool orb_send(entity this, entity to, int sf);
#endif
+REGISTER_NET_TEMP(TE_CSQC_DARKBLINKING); //LegendGuard registers dark blinking nade feature 09-02-2021
+
#ifdef CSQC
+#include <client/draw.qh>
+#include <client/hud/hud.qh>
+
float cvar_cl_nade_type;
string cvar_cl_pokenade_type;
+float cvar_cl_tandemnade_type; //LegendGuard adds new cl variable for emerald nade 01-07-2021
+//LegendGuard sets variables for dark nade 09-02-2021
+float autocvar_hud_panel_darkradar_maximised_zoom_scale = 1;
+float dark_appeartime;
+float dark_fadetime;
+/***************************************************************/
+void HUD_DarkBlinking()
+{
+ // vectors for top right, bottom right, bottom and bottom left corners
+ //vector topright = vec2(vid_conwidth, 0);
+ //vector bottom = vec2(vid_conwidth / 2, vid_conheight);
+ vector bottomright = vec2(vid_conwidth, vid_conheight);
+ //vector bottomleft = vec2(0, vid_conheight);
+
+ /*
+ drawfill function parameters (qcsrc/dpdefs/menudefs.qc):
+ float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
+ */
+ drawfill('0 0 0', bottomright, '0.23 0 0.23', 0.98, DRAWFLAG_NORMAL);
+}
+
+#elif defined(SVQC)
+#include <server/command/common.qh>
+
+void DarkBlinking(entity e)
+{
+ if(e == NULL)
+ return;
+
+ int accepted = VerifyClientEntity(e, true, false);
+
+ if(accepted > 0)
+ {
+ msg_entity = e;
+ WriteHeader(MSG_ONE, TE_CSQC_DARKBLINKING);
+ }
+}
+#endif
+
+#ifdef CSQC
+const int MAX_QUADRATIC2 = 25;
+vector quadratic2_slots[MAX_QUADRATIC2];
+vector quadratic2_dirs[MAX_QUADRATIC2];
+const float QUADRATIC2_SPEED = 150;
+const float QUADRATIC2_TURNSPEED = 0.35;
+const float QUADRATIC2_SIZE = 24;
+const float QUADRATIC2_CHANCE = 0.35;
+float quadratic2_spawntime, quadratic2_fadetime;
+bool quadratic2;
+void HUD_Quadratic2()
+{
+ for(int j = MAX_QUADRATIC2 - 1; j >= 0; --j)
+ {
+ vector slot = quadratic2_slots[j];
+ vector dirs = quadratic2_dirs[j];
+ float oldz = slot.z;
+ if(slot)
+ slot += quadratic2_dirs[j] * QUADRATIC2_SPEED * frametime;
+ slot.z = oldz;
+ //if(slot.z)
+ //slot.z = sin(QUADRATIC2_TURNSPEED * M_PI * time);
+ if(slot.y > vid_conheight || slot.x > vid_conwidth)
+ slot = '0 0 0';
+
+ if(slot == '0 0 0')
+ {
+ if(time > quadratic2_spawntime && random() <= QUADRATIC2_CHANCE) // low chance to spawn!
+ {
+ slot.x = bound(0, (random() * vid_conwidth + 1), vid_conwidth);
+ slot.y = bound(0, (random() * vid_conheight + 1), vid_conheight);
+ slot.z = 0;
+ dirs = vec2(randomvec());
+ quadratic2_spawntime = time + bound(0.05, random() * 0.5, 0.4); // prevent spawning another one for this amount of time!
+ }
+ }
+ else
+ {
+ vector splash_size = vec2(QUADRATIC2_SIZE, QUADRATIC2_SIZE);
+ if(time > dirs.z)
+ {
+ if(random() <= 0.05)
+ slot.z = -1;
+ else
+ slot.z = floor(random() * 9) + 1;
+ dirs.z = time + QUADRATIC2_TURNSPEED;
+ }
+ string chosen_number = ((slot.z == -1) ? "NOOB" : ftos(rint(slot.z)));
+ draw_beginBoldFont();
+ drawcolorcodedstring(vec2(slot), chosen_number, splash_size, 0.95, DRAWFLAG_NORMAL);
+ draw_endBoldFont();
+ }
+
+ quadratic2_slots[j] = slot;
+ quadratic2_dirs[j] = dirs;
+ }
+}
+
+bool darkblink;
+
+STATIC_INIT_LATE(cl_darkblink_override)
+{
+ localcmd("\nalias solve_quadratic2 \"cl_cmd solve_quadratic2 ${* ?}\"\n");
+}
+
+REGISTER_MUTATOR(cl_darkblink, true);
+
+MUTATOR_HOOKFUNCTION(cl_darkblink, DrawScoreboard)
+{
+ return darkblink;
+}
+
+MUTATOR_HOOKFUNCTION(cl_darkblink, HUD_Draw_overlay)
+{
+ if(!darkblink && !quadratic2)
+ return false;
+
+ if(time <= dark_fadetime && autocvar_hud_panel_darkradar_maximised_zoom_scale == 1)
+ {
+ HUD_DarkBlinking();
+ return false;
+ }
+ else
+ darkblink = false;
+
+ if(time <= quadratic2_fadetime)
+ {
+ HUD_Quadratic2();
+ // don't return true, we want regular HUD effects!
+ }
+ else
+ quadratic2 = false;
+
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(cl_darkblink, CSQC_ConsoleCommand)
+{
+ if(MUTATOR_RETURNVALUE) // command was already handled?
+ return;
+
+ string cmd_name = M_ARGV(0, string);
+ //int cmd_argc = M_ARGV(2, int);
+
+ if(cmd_name == "solve_quadratic2")
+ {
+ quadratic2 = true;
+ quadratic2_fadetime = time + 5;
+ return true;
+ }
+}
+
+NET_HANDLE(TE_CSQC_DARKBLINKING, bool isNew)
+{
+ return = true;
+
+ if(darkblink)
+ return;
+
+ localcmd("play2 sound/misc/blind\n");
+ darkblink = true;
+ dark_appeartime = time;
+ dark_fadetime = time + 9;
+}
+#endif
+/***************************************************************/
+#ifdef CSQC
bool Projectile_isnade(int proj); // TODO: remove
void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expand_time); // TODO: mutator