Xonotic
spider.qc
Go to the documentation of this file.
1 #include "spider.qh"
2 
3 #if defined(SVQC)
4  #include <common/mutators/base.qh>
5 #endif
6 
7 #ifdef SVQC
8 
9 .float spider_web_delay;
10 
11 float autocvar_g_monster_spider_attack_web_damagetime;
12 float autocvar_g_monster_spider_attack_web_speed;
13 float autocvar_g_monster_spider_attack_web_speed_up;
14 float autocvar_g_monster_spider_attack_web_delay;
15 
16 float autocvar_g_monster_spider_attack_bite_damage;
17 float autocvar_g_monster_spider_attack_bite_delay;
18 
19 void M_Spider_Attack_Web(entity this);
20 
21 REGISTER_MUTATOR(spiderweb, true);
22 
23 MUTATOR_HOOKFUNCTION(spiderweb, PlayerPhysics_UpdateStats)
24 {
25  entity player = M_ARGV(0, entity);
26 
27  if(StatusEffects_active(STATUSEFFECT_Webbed, player))
28  STAT(MOVEVARS_HIGHSPEED, player) *= 0.5;
29 }
30 
31 MUTATOR_HOOKFUNCTION(spiderweb, MonsterMove)
32 {
33  entity mon = M_ARGV(0, entity);
34 
35  if(StatusEffects_active(STATUSEFFECT_Webbed, mon))
36  {
37  M_ARGV(1, float) *= 0.5; // run speed
38  M_ARGV(2, float) *= 0.5; // walk speed
39  }
40 }
41 
42 SOUND(SpiderAttack_FIRE, W_Sound("electro_fire"));
43 METHOD(SpiderAttack, wr_think, void(SpiderAttack thiswep, entity actor, .entity weaponentity, int fire))
44 {
45  TC(SpiderAttack, thiswep);
46  bool isPlayer = IS_PLAYER(actor);
47  if (fire & 1)
48  if ((!isPlayer && time >= actor.spider_web_delay) || weapon_prepareattack(thiswep, actor, weaponentity, false, autocvar_g_monster_spider_attack_web_delay)) {
49  if (!isPlayer) {
50  actor.spider_web_delay = time + 3;
51  setanim(actor, actor.anim_shoot, true, true, true);
52  actor.attack_finished_single[0] = time + (autocvar_g_monster_spider_attack_web_delay);
53  actor.anim_finished = time + 1;
54  }
55  if (isPlayer) actor.enemy = Monster_FindTarget(actor);
56  monster_makevectors(actor, actor.enemy);
57  W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_SpiderAttack_FIRE, CH_WEAPON_B, 0, DEATH_MONSTER_SPIDER.m_id);
58  if (!isPlayer) w_shotdir = normalize((actor.enemy.origin + '0 0 10') - actor.origin);
59  M_Spider_Attack_Web(actor);
60  weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, 0, w_ready);
61  return;
62  }
63  if (fire & 2)
64  if (!isPlayer || weapon_prepareattack(thiswep, actor, weaponentity, true, 0.5)) {
65  if (isPlayer) {
66  actor.enemy = Monster_FindTarget(actor);
67  actor.attack_range = 60;
68  }
69  Monster_Attack_Melee(actor, actor.enemy, (autocvar_g_monster_spider_attack_bite_damage), ((random() > 0.5) ? actor.anim_melee : actor.anim_shoot), actor.attack_range, (autocvar_g_monster_spider_attack_bite_delay), DEATH_MONSTER_SPIDER.m_id, true);
70  weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, 0, w_ready);
71  }
72 }
73 
74 float autocvar_g_monster_spider_health;
75 float autocvar_g_monster_spider_damageforcescale = 0.6;
76 float autocvar_g_monster_spider_speed_stop;
77 float autocvar_g_monster_spider_speed_run;
78 float autocvar_g_monster_spider_speed_walk;
79 
80 /*
81 const float spider_anim_idle = 0;
82 const float spider_anim_walk = 1;
83 const float spider_anim_attack = 2;
84 const float spider_anim_attack2 = 3;
85 */
86 
87 void M_Spider_Attack_Web_Explode(entity this)
88 {
89  if(this)
90  {
91  Send_Effect(EFFECT_ELECTRO_IMPACT, this.origin, '0 0 0', 1);
92  RadiusDamage(this, this.realowner, 0, 0, 25, NULL, NULL, 25, this.projectiledeathtype, DMG_NOWEP, NULL);
93 
94  FOREACH_ENTITY_RADIUS(this.origin, 25, it != this && it.takedamage && !IS_DEAD(it) && GetResource(it, RES_HEALTH) > 0 && it.monsterdef != MON_SPIDER,
95  {
96  StatusEffects_apply(STATUSEFFECT_Webbed, it, time + autocvar_g_monster_spider_attack_web_damagetime, 0);
97  });
98 
99  delete(this);
100  }
101 }
102 
103 void M_Spider_Attack_Web_Explode_use(entity this, entity actor, entity trigger)
104 {
105  M_Spider_Attack_Web_Explode(this);
106 }
107 
108 void M_Spider_Attack_Web_Touch(entity this, entity toucher)
109 {
110  PROJECTILE_TOUCH(this, toucher);
111 
112  M_Spider_Attack_Web_Explode(this);
113 }
114 
115 void M_Spider_Attack_Web(entity this)
116 {
117  sound(this, CH_SHOTS, SND_ELECTRO_FIRE2, VOL_BASE, ATTEN_NORM);
118 
119  entity proj = new(plasma);
120  proj.owner = proj.realowner = this;
121  proj.use = M_Spider_Attack_Web_Explode_use;
123  proj.bot_dodge = true;
124  proj.bot_dodgerating = 0;
125  proj.nextthink = time + 5;
127  proj.projectiledeathtype = DEATH_MONSTER_SPIDER.m_id;
128  setorigin(proj, CENTER_OR_VIEWOFS(this));
129 
130  //proj.glow_size = 50;
131  //proj.glow_color = 45;
133  W_SetupProjVelocity_Explicit(proj, v_forward, v_up, (autocvar_g_monster_spider_attack_web_speed), (autocvar_g_monster_spider_attack_web_speed_up), 0, 0, false);
134  settouch(proj, M_Spider_Attack_Web_Touch);
135  setsize(proj, '-4 -4 -4', '4 4 4');
136  proj.takedamage = DAMAGE_NO;
137  proj.damageforcescale = 0;
138  SetResourceExplicit(proj, RES_HEALTH, 500);
139  proj.event_damage = func_null;
140  proj.flags = FL_PROJECTILE;
141  IL_PUSH(g_projectiles, proj);
142  IL_PUSH(g_bot_dodge, proj);
143  proj.damagedbycontents = true;
145 
146  proj.bouncefactor = 0.3;
147  proj.bouncestop = 0.05;
148  proj.missile_flags = MIF_SPLASH | MIF_ARC;
149 
150  CSQCProjectile(proj, true, PROJECTILE_ELECTRO, true);
151 }
152 
153 bool M_Spider_Attack(int attack_type, entity actor, entity targ, .entity weaponentity)
154 {
155  Weapon wep = WEP_SPIDER_ATTACK;
156  switch(attack_type)
157  {
159  {
160  wep.wr_think(wep, actor, weaponentity, 2);
161  return true;
162  }
164  {
165  wep.wr_think(wep, actor, weaponentity, 1);
166  return true;
167  }
168  }
169 
170  return false;
171 }
172 
173 spawnfunc(monster_spider) { Monster_Spawn(this, true, MON_SPIDER); }
174 #endif // SVQC
175 
176 #ifdef SVQC
177 METHOD(Spider, mr_think, bool(Spider this, entity actor))
178 {
179  TC(Spider, this);
180  return true;
181 }
182 
183 METHOD(Spider, mr_pain, float(Spider this, entity actor, float damage_take, entity attacker, float deathtype))
184 {
185  TC(Spider, this);
186  return damage_take;
187 }
188 
189 METHOD(Spider, mr_death, bool(Spider this, entity actor))
190 {
191  TC(Spider, this);
192  setanim(actor, actor.anim_melee, false, true, true);
193  actor.angles_x = 180;
194  return true;
195 }
196 #endif
197 #ifdef GAMEQC
198 METHOD(Spider, mr_anim, bool(Spider this, entity actor))
199 {
200  TC(Spider, this);
201  vector none = '0 0 0';
202  actor.anim_walk = animfixfps(actor, '1 1 1', none);
203  actor.anim_idle = animfixfps(actor, '0 1 1', none);
204  actor.anim_melee = animfixfps(actor, '2 1 5', none); // analyze models and set framerate
205  actor.anim_shoot = animfixfps(actor, '3 1 5', none); // analyze models and set framerate
206  actor.anim_run = animfixfps(actor, '1 1 1', none);
207  return true;
208 }
209 #endif
210 #ifdef SVQC
211 METHOD(Spider, mr_setup, bool(Spider this, entity actor))
212 {
213  TC(Spider, this);
214  if(!GetResource(this, RES_HEALTH)) SetResourceExplicit(actor, RES_HEALTH, autocvar_g_monster_spider_health);
215  if(!actor.speed) { actor.speed = (autocvar_g_monster_spider_speed_walk); }
216  if(!actor.speed2) { actor.speed2 = (autocvar_g_monster_spider_speed_run); }
217  if(!actor.stopspeed) { actor.stopspeed = (autocvar_g_monster_spider_speed_stop); }
218  if(!actor.damageforcescale) { actor.damageforcescale = (autocvar_g_monster_spider_damageforcescale); }
219 
220  actor.monster_loot = ITEM_HealthMedium;
221  actor.monster_attackfunc = M_Spider_Attack;
222 
223  return true;
224 }
225 #endif
entity Monster_FindTarget(entity this)
Definition: sv_monsters.qc:126
#define PROJECTILE_MAKETRIGGER(e)
Definition: common.qh:29
#define REGISTER_MUTATOR(id, dependence)
Definition: base.qh:263
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
Definition: cl_resources.qc:15
const int MIF_ARC
Definition: common.qh:35
#define setanim(...)
Definition: anim.qh:45
const int MIF_SPLASH
Definition: common.qh:34
bool Monster_Attack_Melee(entity this, entity targ, float damg, vector anim, float er, float animtime, int deathtype, bool dostop)
Definition: sv_monsters.qc:362
IntrusiveList g_damagedbycontents
Definition: damage.qh:155
entity() spawn
Definition: spider.qh:9
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)
vector w_shotdir
Definition: tracing.qh:19
spawnfunc(info_player_attacker)
Definition: sv_assault.qc:283
origin
Definition: ent_cs.qc:114
string W_Sound(string w_snd)
Definition: all.qc:281
float MOVETYPE_BOUNCE
Definition: progsdefs.qc:256
#define METHOD(cname, name, prototype)
Definition: oo.qh:257
void CSQCProjectile(entity e, float clientanimate, int type, float docull)
#define DMG_NOWEP
Definition: damage.qh:126
IntrusiveList g_bot_dodge
Definition: api.qh:150
#define PROJECTILE_TOUCH(e, t)
Definition: common.qh:27
RES_HEALTH
Definition: ent_cs.qc:126
void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float pSpeed, float pUpSpeed, float pZSpeed, float spread, float forceAbsolute)
Definition: tracing.qc:185
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
vector v_up
Definition: csprogsdefs.qc:31
bool weapon_prepareattack(Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)
const int MONSTER_ATTACK_MELEE
Definition: sv_monsters.qh:70
#define NULL
Definition: post.qh:17
const float VOL_BASE
Definition: sound.qh:36
#define TC(T, sym)
Definition: _all.inc:82
const int MONSTER_ATTACK_RANGED
Definition: sv_monsters.qh:71
#define M_ARGV(x, type)
Definition: events.qh:17
#define IS_DEAD(s)
Definition: utils.qh:26
const float ATTEN_NORM
Definition: sound.qh:30
#define W_SetupShot_Dir(ent, wepent, s_forward, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition: tracing.qh:31
void monster_makevectors(entity this, entity targ)
Definition: sv_monsters.qc:66
const int CH_SHOTS
Definition: sound.qh:14
#define CENTER_OR_VIEWOFS(ent)
Definition: utils.qh:28
vector(float skel, float bonenum) _skel_get_boneabs_hidden
IntrusiveList g_projectiles
Definition: common.qh:46
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
bool Monster_Spawn(entity this, bool check_appear, Monster mon)
const int PROJECTILE_ELECTRO
Definition: projectiles.qh:3
void weapon_thinkf(entity actor,.entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,.entity weaponentity, int fire) func)
float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype,.entity weaponentity, entity directhitentity)
Definition: damage.qc:1057
entity realowner
Definition: common.qh:25
setorigin(ent, v)
#define setthink(e, f)
#define MUTATOR_HOOKFUNCTION(...)
Definition: base.qh:310
void adaptor_think2use_hittype_splash(entity this)
Definition: common.qc:110
#define sound(e, c, s, v, a)
Definition: sound.qh:52
#define SOUND(name, path)
Definition: all.qh:30
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition: weapon.qh:41
float time
Definition: csprogsdefs.qc:16
const int CH_WEAPON_B
Definition: sound.qh:8
float DAMAGE_NO
Definition: progsdefs.qc:282
void set_movetype(entity this, int mt)
#define IS_PLAYER(v)
Definition: utils.qh:9
var void func_null()
vector v_forward
Definition: csprogsdefs.qc:31
int projectiledeathtype
Definition: common.qh:20