X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Fweapons%2Fweapon%2Ffireball.qc;h=8c0d928db883e5e03d4342f1237402eaf80dcb6c;hb=92749b51e06f4fd2a89d7593a9db7500818ad2fd;hp=c334932f165f74fb96e7b120522584337460bbc3;hpb=1af8ea71282d19f66c96622815c68943eaa36aba;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/weapons/weapon/fireball.qc b/qcsrc/common/weapons/weapon/fireball.qc index c334932f1..8c0d928db 100644 --- a/qcsrc/common/weapons/weapon/fireball.qc +++ b/qcsrc/common/weapons/weapon/fireball.qc @@ -1,53 +1,58 @@ #ifndef IMPLEMENTATION -REGISTER_WEAPON( -/* WEP_##id */ FIREBALL, -/* function */ W_Fireball, -/* ammotype */ ammo_none, -/* impulse */ 9, -/* flags */ WEP_FLAG_SUPERWEAPON | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_MID, -/* color */ '1 0.5 0', -/* modelname */ "fireball", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairfireball", -/* wepimg */ "weaponfireball", -/* refname */ "fireball", -/* wepname */ _("Fireball") -); - -#define FIREBALL_SETTINGS(w_cvar,w_prop) FIREBALL_SETTINGS_LIST(w_cvar, w_prop, FIREBALL, fireball) -#define FIREBALL_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, BOTH, animtime) \ - w_cvar(id, sn, BOTH, refire) \ - w_cvar(id, sn, BOTH, damage) \ - w_cvar(id, sn, BOTH, damageforcescale) \ - w_cvar(id, sn, BOTH, speed) \ - w_cvar(id, sn, BOTH, spread) \ - w_cvar(id, sn, BOTH, lifetime) \ - w_cvar(id, sn, BOTH, laserburntime) \ - w_cvar(id, sn, BOTH, laserdamage) \ - w_cvar(id, sn, BOTH, laseredgedamage) \ - w_cvar(id, sn, BOTH, laserradius) \ - w_cvar(id, sn, PRI, edgedamage) \ - w_cvar(id, sn, PRI, force) \ - w_cvar(id, sn, PRI, radius) \ - w_cvar(id, sn, PRI, health) \ - w_cvar(id, sn, PRI, refire2) \ - w_cvar(id, sn, PRI, bfgdamage) \ - w_cvar(id, sn, PRI, bfgforce) \ - w_cvar(id, sn, PRI, bfgradius) \ - w_cvar(id, sn, SEC, damagetime) \ - w_cvar(id, sn, SEC, speed_up) \ - w_cvar(id, sn, SEC, speed_z) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) +CLASS(Fireball, Weapon) +/* ammotype */ //ATTRIB(Fireball, ammo_field, .int, ammo_none) +/* impulse */ ATTRIB(Fireball, impulse, int, 9) +/* flags */ ATTRIB(Fireball, spawnflags, int, WEP_FLAG_SUPERWEAPON | WEP_TYPE_SPLASH); +/* rating */ ATTRIB(Fireball, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID); +/* color */ ATTRIB(Fireball, wpcolor, vector, '1 0.5 0'); +/* modelname */ ATTRIB(Fireball, mdl, string, "fireball"); +#ifndef MENUQC +/* model */ ATTRIB(Fireball, m_model, Model, MDL_FIREBALL_ITEM); +#endif +/* crosshair */ ATTRIB(Fireball, w_crosshair, string, "gfx/crosshairfireball"); +/* crosshair */ //ATTRIB(Fireball, w_crosshair_size, float, 0.65); +/* wepimg */ ATTRIB(Fireball, model2, string, "weaponfireball"); +/* refname */ ATTRIB(Fireball, netname, string, "fireball"); +/* wepname */ ATTRIB(Fireball, m_name, string, _("Fireball")); + +#define X(BEGIN, P, END, class, prefix) \ + BEGIN(class) \ + P(class, prefix, animtime, float, BOTH) \ + P(class, prefix, bfgdamage, float, PRI) \ + P(class, prefix, bfgforce, float, PRI) \ + P(class, prefix, bfgradius, float, PRI) \ + P(class, prefix, damageforcescale, float, BOTH) \ + P(class, prefix, damagetime, float, SEC) \ + P(class, prefix, damage, float, BOTH) \ + P(class, prefix, edgedamage, float, PRI) \ + P(class, prefix, force, float, PRI) \ + P(class, prefix, health, float, PRI) \ + P(class, prefix, laserburntime, float, BOTH) \ + P(class, prefix, laserdamage, float, BOTH) \ + P(class, prefix, laseredgedamage, float, BOTH) \ + P(class, prefix, laserradius, float, BOTH) \ + P(class, prefix, lifetime, float, BOTH) \ + P(class, prefix, radius, float, PRI) \ + P(class, prefix, refire2, float, PRI) \ + P(class, prefix, refire, float, BOTH) \ + P(class, prefix, speed, float, BOTH) \ + P(class, prefix, speed_up, float, SEC) \ + P(class, prefix, speed_z, float, SEC) \ + P(class, prefix, spread, float, BOTH) \ + P(class, prefix, switchdelay_drop, float, NONE) \ + P(class, prefix, switchdelay_raise, float, NONE) \ + P(class, prefix, weaponreplace, string,NONE) \ + P(class, prefix, weaponstartoverride, float, NONE) \ + P(class, prefix, weaponstart, float, NONE) \ + P(class, prefix, weaponthrowable, float, NONE) \ + END() + W_PROPS(X, Fireball, fireball) +#undef X + +ENDCLASS(Fireball) +REGISTER_WEAPON(FIREBALL, fireball, NEW(Fireball)); #ifdef SVQC -FIREBALL_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) .float bot_primary_fireballmooth; // whatever a mooth is .vector fireball_impactvec; .float fireball_primarytime; @@ -55,9 +60,9 @@ FIREBALL_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) #endif #ifdef IMPLEMENTATION #ifdef SVQC -spawnfunc(weapon_fireball) { weapon_defaultspawnfunc(WEP_FIREBALL.m_id); } +spawnfunc(weapon_fireball) { weapon_defaultspawnfunc(this, WEP_FIREBALL); } -void W_Fireball_Explode(void) +void W_Fireball_Explode() {SELFPARAM(); entity e; float dist; @@ -107,7 +112,7 @@ void W_Fireball_Explode(void) remove(self); } -void W_Fireball_TouchExplode(void) +void W_Fireball_TouchExplode() { PROJECTILE_TOUCH; W_Fireball_Explode(); @@ -147,7 +152,7 @@ void W_Fireball_LaserPlay(float dt, float dist, float damage, float edgedamage, } } -void W_Fireball_Think(void) +void W_Fireball_Think() {SELFPARAM(); if(time > self.pushltime) { @@ -162,23 +167,23 @@ void W_Fireball_Think(void) self.nextthink = time + 0.1; } -void W_Fireball_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) -{SELFPARAM(); - if(self.health <= 0) +void W_Fireball_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) +{ + if(this.health <= 0) return; - if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions + if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) // no exceptions return; // g_projectiles_damage says to halt - self.health = self.health - damage; - if(self.health <= 0) + this.health = this.health - damage; + if(this.health <= 0) { - self.cnt = 1; - W_PrepareExplosionByDamage(attacker, W_Fireball_Explode); + this.cnt = 1; + WITH(entity, self, this, W_PrepareExplosionByDamage(attacker, W_Fireball_Explode)); } } -void W_Fireball_Attack1(void) +void W_Fireball_Attack1() {SELFPARAM(); entity proj; @@ -186,8 +191,7 @@ void W_Fireball_Attack1(void) Send_Effect(EFFECT_FIREBALL_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - proj = spawn(); - proj.classname = "plasma_prim"; + proj = new(plasma_prim); proj.owner = proj.realowner = self; proj.bot_dodge = true; proj.bot_dodgerating = WEP_CVAR_PRI(fireball, damage); @@ -224,38 +228,38 @@ void W_Fireball_AttackEffect(float i, vector f_diff) Send_Effect(EFFECT_FIREBALL_PRE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); } -void W_Fireball_Attack1_Frame4(void) +void W_Fireball_Attack1_Frame4(Weapon thiswep, entity actor, .entity weaponentity, int fire) { W_Fireball_Attack1(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), w_ready); + weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), w_ready); } -void W_Fireball_Attack1_Frame3(void) +void W_Fireball_Attack1_Frame3(Weapon thiswep, entity actor, .entity weaponentity, int fire) { W_Fireball_AttackEffect(0, '+1.25 +3.75 0'); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame4); + weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame4); } -void W_Fireball_Attack1_Frame2(void) +void W_Fireball_Attack1_Frame2(Weapon thiswep, entity actor, .entity weaponentity, int fire) { W_Fireball_AttackEffect(0, '-1.25 +3.75 0'); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame3); + weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame3); } -void W_Fireball_Attack1_Frame1(void) +void W_Fireball_Attack1_Frame1(Weapon thiswep, entity actor, .entity weaponentity, int fire) { W_Fireball_AttackEffect(1, '+1.25 -3.75 0'); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame2); + weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame2); } -void W_Fireball_Attack1_Frame0(void) +void W_Fireball_Attack1_Frame0(Weapon thiswep, entity actor, .entity weaponentity, int fire) {SELFPARAM(); W_Fireball_AttackEffect(0, '-1.25 -3.75 0'); sound(self, CH_WEAPON_SINGLE, SND_FIREBALL_PREFIRE2, VOL_BASE, ATTEN_NORM); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame1); + weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame1); } -void W_Fireball_Firemine_Think(void) +void W_Fireball_Firemine_Think() {SELFPARAM(); if(time > self.pushltime) { @@ -266,7 +270,7 @@ void W_Fireball_Firemine_Think(void) // make it "hot" once it leaves its owner if(self.owner) { - if(vlen(self.origin - self.owner.origin - self.owner.view_ofs) > WEP_CVAR_SEC(fireball, laserradius)) + if(vdist(self.origin - self.owner.origin - self.owner.view_ofs, >, WEP_CVAR_SEC(fireball, laserradius))) { self.cnt += 1; if(self.cnt == 3) @@ -281,7 +285,7 @@ void W_Fireball_Firemine_Think(void) self.nextthink = time + 0.1; } -void W_Fireball_Firemine_Touch(void) +void W_Fireball_Firemine_Touch() {SELFPARAM(); PROJECTILE_TOUCH; if(other.takedamage == DAMAGE_AIM) @@ -293,7 +297,7 @@ void W_Fireball_Firemine_Touch(void) self.projectiledeathtype |= HITTYPE_BOUNCE; } -void W_Fireball_Attack2(void) +void W_Fireball_Attack2() {SELFPARAM(); entity proj; vector f_diff; @@ -322,9 +326,8 @@ void W_Fireball_Attack2(void) Send_Effect(EFFECT_FIREBALL_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - proj = spawn(); + proj = new(grenade); proj.owner = proj.realowner = self; - proj.classname = "grenade"; proj.bot_dodge = true; proj.bot_dodgerating = WEP_CVAR_SEC(fireball, damage); proj.movetype = MOVETYPE_BOUNCE; @@ -348,131 +351,96 @@ void W_Fireball_Attack2(void) MUTATOR_CALLHOOK(EditProjectile, self, proj); } -bool W_Fireball(int req) -{SELFPARAM(); - switch(req) - { - case WR_AIM: - { - self.BUTTON_ATCK = false; - self.BUTTON_ATCK2 = false; - if(self.bot_primary_fireballmooth == 0) - { - if(bot_aim(WEP_CVAR_PRI(fireball, speed), 0, WEP_CVAR_PRI(fireball, lifetime), false)) - { - self.BUTTON_ATCK = true; - if(random() < 0.02) self.bot_primary_fireballmooth = 0; - } - } - else - { - if(bot_aim(WEP_CVAR_SEC(fireball, speed), WEP_CVAR_SEC(fireball, speed_up), WEP_CVAR_SEC(fireball, lifetime), true)) - { - self.BUTTON_ATCK2 = true; - if(random() < 0.01) self.bot_primary_fireballmooth = 1; - } - } - - return true; - } - case WR_THINK: - { - if(self.BUTTON_ATCK) - { - if(time >= self.fireball_primarytime) - if(weapon_prepareattack(0, WEP_CVAR_PRI(fireball, refire))) - { - W_Fireball_Attack1_Frame0(); - self.fireball_primarytime = time + WEP_CVAR_PRI(fireball, refire2) * W_WeaponRateFactor(); - } - } - else if(self.BUTTON_ATCK2) - { - if(weapon_prepareattack(1, WEP_CVAR_SEC(fireball, refire))) - { - W_Fireball_Attack2(); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(fireball, animtime), w_ready); - } - } - - return true; - } - case WR_INIT: - { - FIREBALL_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP); - return true; - } - case WR_SETUP: - { - self.ammo_field = ammo_none; - return true; - } - case WR_CHECKAMMO1: - case WR_CHECKAMMO2: - { - return true; // fireball has infinite ammo - } - case WR_CONFIG: - { - FIREBALL_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS); - return true; - } - case WR_RESETPLAYER: - { - self.fireball_primarytime = time; - return true; - } - case WR_SUICIDEMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_FIREBALL_SUICIDE_FIREMINE; - else - return WEAPON_FIREBALL_SUICIDE_BLAST; - } - case WR_KILLMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_FIREBALL_MURDER_FIREMINE; - else - return WEAPON_FIREBALL_MURDER_BLAST; - } - } - return false; +METHOD(Fireball, wr_aim, void(entity thiswep)) +{ + PHYS_INPUT_BUTTON_ATCK(self) = false; + PHYS_INPUT_BUTTON_ATCK2(self) = false; + if(self.bot_primary_fireballmooth == 0) + { + if(bot_aim(WEP_CVAR_PRI(fireball, speed), 0, WEP_CVAR_PRI(fireball, lifetime), false)) + { + PHYS_INPUT_BUTTON_ATCK(self) = true; + if(random() < 0.02) self.bot_primary_fireballmooth = 0; + } + } + else + { + if(bot_aim(WEP_CVAR_SEC(fireball, speed), WEP_CVAR_SEC(fireball, speed_up), WEP_CVAR_SEC(fireball, lifetime), true)) + { + PHYS_INPUT_BUTTON_ATCK2(self) = true; + if(random() < 0.01) self.bot_primary_fireballmooth = 1; + } + } } +METHOD(Fireball, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire)) +{ + if(fire & 1) + { + if(time >= actor.fireball_primarytime) + if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(fireball, refire))) + { + W_Fireball_Attack1_Frame0(thiswep, actor, weaponentity, fire); + actor.fireball_primarytime = time + WEP_CVAR_PRI(fireball, refire2) * W_WeaponRateFactor(); + } + } + else if(fire & 2) + { + if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(fireball, refire))) + { + W_Fireball_Attack2(); + weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(fireball, animtime), w_ready); + } + } +} +METHOD(Fireball, wr_setup, void(entity thiswep)) +{ + self.ammo_field = ammo_none; +} +METHOD(Fireball, wr_checkammo1, bool(entity thiswep)) +{ + return true; // infinite ammo +} +METHOD(Fireball, wr_checkammo2, bool(entity thiswep)) +{ + return true; // fireball has infinite ammo +} +METHOD(Fireball, wr_resetplayer, void(entity thiswep)) +{ + self.fireball_primarytime = time; +} +METHOD(Fireball, wr_suicidemessage, Notification(entity thiswep)) +{ + if(w_deathtype & HITTYPE_SECONDARY) + return WEAPON_FIREBALL_SUICIDE_FIREMINE; + else + return WEAPON_FIREBALL_SUICIDE_BLAST; +} +METHOD(Fireball, wr_killmessage, Notification(entity thiswep)) +{ + if(w_deathtype & HITTYPE_SECONDARY) + return WEAPON_FIREBALL_MURDER_FIREMINE; + else + return WEAPON_FIREBALL_MURDER_BLAST; +} + #endif #ifdef CSQC -bool W_Fireball(int req) -{SELFPARAM(); - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - if(w_deathtype & HITTYPE_SECONDARY) - { - // firemine goes out silently - } - else - { - org2 = w_org + w_backoff * 16; - pointparticles(particleeffectnum(EFFECT_FIREBALL_EXPLODE), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, SND_FIREBALL_IMPACT2, VOL_BASE, ATTEN_NORM * 0.25); // long range boom - } - - return true; - } - case WR_INIT: - { - return true; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return false; - } - } - return false; + +METHOD(Fireball, wr_impacteffect, void(entity thiswep)) +{ + vector org2; + if(w_deathtype & HITTYPE_SECONDARY) + { + // firemine goes out silently + } + else + { + org2 = w_org + w_backoff * 16; + pointparticles(EFFECT_FIREBALL_EXPLODE, org2, '0 0 0', 1); + if(!w_issilent) + sound(self, CH_SHOTS, SND_FIREBALL_IMPACT2, VOL_BASE, ATTEN_NORM * 0.25); // long range boom + } } + #endif #endif