]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/monsters/monster/spider.qc
Remove enforcer & all W_ attack functions from the monster code
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / monsters / monster / spider.qc
1 #ifndef MENUQC
2 // size
3 const vector SPIDER_MIN = '-18 -18 -25';
4 const vector SPIDER_MAX = '18 18 30';
5
6 // model
7 string SPIDER_MODEL = "models/monsters/spider.dpm";
8
9 #endif
10
11 #ifdef SVQC
12 // cvars
13 float autocvar_g_monster_spider;
14 float autocvar_g_monster_spider_stopspeed;
15 float autocvar_g_monster_spider_attack_leap_delay;
16 float autocvar_g_monster_spider_attack_stand_damage;
17 float autocvar_g_monster_spider_attack_stand_delay;
18 float autocvar_g_monster_spider_attack_fire_time;
19 float autocvar_g_monster_spider_health;
20 float autocvar_g_monster_spider_speed_walk;
21 float autocvar_g_monster_spider_speed_run;
22 float autocvar_g_monster_spider_attack_type;
23
24 // animations
25 const float spider_anim_idle            = 0;
26 const float spider_anim_walk            = 1;
27 const float spider_anim_attack          = 2;
28 const float spider_anim_attack2         = 3;
29
30 .float spider_type; // used to switch between fire & ice attacks
31 const float SPIDER_TYPE_ICE             = 0;
32 const float SPIDER_TYPE_FIRE    = 1;
33
34 void spider_attack_standing()
35 {
36         float dot = 0, bigdmg = autocvar_g_monster_spider_attack_stand_damage * self.scale;
37
38         self.velocity_x = 0;
39         self.velocity_y = 0;
40
41         makevectors (self.angles);
42         dot = normalize (self.enemy.origin - self.origin) * v_forward;
43         if(dot > 0.3)
44                 Damage(self.enemy, self, self, bigdmg * monster_skill, DEATH_MONSTER_SPIDER, self.origin, '0 0 0');
45         
46         monsters_setframe((random() > 0.5) ? spider_anim_attack : spider_anim_attack2);
47
48         self.attack_finished_single = time + autocvar_g_monster_spider_attack_stand_delay;
49 }
50
51 void spider_web_explode ()
52 {
53         float damg = 0, edamg = 0, rad = 1;
54         switch(self.realowner.spider_type)
55         {
56                 case SPIDER_TYPE_ICE:
57                         break; // no change
58                 case SPIDER_TYPE_FIRE:
59                         damg = 15;
60                         rad = 25;
61                         edamg = 6;
62                         break;
63         }
64         
65         RadiusDamage (self, self.realowner, damg, edamg, rad, world, 0, self.projectiledeathtype, other);
66         
67         remove (self);
68 }
69
70 void spider_web_touch ()
71 {
72         PROJECTILE_TOUCH;
73         
74         if(other.takedamage == DAMAGE_AIM)
75         switch(self.realowner.spider_type)
76         {
77                 case SPIDER_TYPE_ICE:
78                         Freeze(other, 0.3);
79                         break;
80                 case SPIDER_TYPE_FIRE:
81                         Fire_AddDamage(other, self.realowner, 5 * monster_skill, autocvar_g_monster_spider_attack_fire_time, DEATH_MONSTER_SPIDER_FIRE);
82                         break;
83         }
84                 
85         spider_web_explode();
86 }
87
88 void spider_shootweb(float ptype)
89 {
90         float p = 0, dt = 0;
91         string snd = "";
92         switch(ptype)
93         {
94                 case SPIDER_TYPE_ICE:
95                         p = PROJECTILE_ELECTRO;
96                         dt = WEP_ELECTRO;
97                         snd = "weapons/electro_fire2.wav";
98                         break;
99                 case SPIDER_TYPE_FIRE:
100                         p = ((self.scale >= 2) ? PROJECTILE_FIREBALL : PROJECTILE_FIREMINE);
101                         dt = WEP_FIREBALL;
102                         snd = "weapons/fireball_fire.wav";
103                         break;
104         }
105         
106         vector fmins = ((self.scale >= 2) ? '-16 -16 -16' : '-4 -4 -4'), fmaxs = ((self.scale >= 2) ? '16 16 16' : '4 4 4');    
107         
108         entity proj = world;
109         
110         makevectors(self.angles);
111
112         W_SetupShot_ProjectileSize(self, fmins, fmaxs, FALSE, 2, snd, CH_WEAPON_A, 0);
113
114         w_shotdir = v_forward; // no TrueAim for grenades please
115
116         proj = spawn ();
117         proj.classname = "plasma";
118         proj.owner = proj.realowner = self;
119         proj.use = spider_web_touch;
120         proj.think = adaptor_think2use_hittype_splash;
121         proj.bot_dodge = TRUE;
122         proj.bot_dodgerating = 0;
123         proj.nextthink = time + 5;
124         PROJECTILE_MAKETRIGGER(proj);
125         proj.projectiledeathtype = dt | HITTYPE_SECONDARY;
126         setorigin(proj, w_shotorg);
127
128         //proj.glow_size = 50;
129         //proj.glow_color = 45;
130         proj.movetype = MOVETYPE_BOUNCE;
131         W_SETUPPROJECTILEVELOCITY_UP(proj, g_monster_spider_attack_web);
132         proj.touch = spider_web_touch;
133         setsize(proj, fmins, fmaxs);
134         proj.takedamage = DAMAGE_NO;
135         proj.damageforcescale = 0;
136         proj.health = 500;
137         proj.event_damage = func_null;
138         proj.flags = FL_PROJECTILE;
139         proj.damagedbycontents = TRUE;
140
141         proj.bouncefactor = 0.3;
142         proj.bouncestop = 0.05;
143         proj.missile_flags = MIF_SPLASH | MIF_ARC;
144
145         CSQCProjectile(proj, TRUE, p, FALSE); // no culling, it has sound
146 }
147
148 void spider_attack_leap()
149 {
150         vector angles_face = vectoangles(self.enemy.origin - self.origin);
151
152         // face the enemy
153         monsters_setframe(spider_anim_attack2);
154         self.angles_y = angles_face_y ;
155         self.attack_finished_single = time + autocvar_g_monster_spider_attack_leap_delay;
156         
157         makevectors(self.angles);
158         
159         spider_shootweb(self.spider_type);
160 }
161
162 float spider_attack_ranged()
163 {
164         if(self.enemy.frozen || self.enemy.freezetag_frozen)
165                 return FALSE;
166                 
167         spider_attack_leap();
168         return TRUE;
169 }
170
171 void spider_think()
172 {
173         self.think = spider_think;
174         self.nextthink = time + self.ticrate;
175         
176         monster_move(autocvar_g_monster_spider_speed_run, autocvar_g_monster_spider_speed_walk, autocvar_g_monster_spider_stopspeed, spider_anim_walk, spider_anim_walk, spider_anim_idle);
177 }
178
179 void spider_die ()
180 {
181         Monster_CheckDropCvars ("spider");
182         
183         self.think = Monster_Fade;
184         self.nextthink = time + 5;
185         monsters_setframe(spider_anim_attack);
186         self.angles += '180 0 0';
187         
188         monster_hook_death(); // for post-death mods
189 }
190
191 void spider_spawn() 
192 {
193         if not(self.health)
194                 self.health = autocvar_g_monster_spider_health * self.scale;
195         
196         self.classname                  = "monster_spider";
197         self.nextthink                  = time + random() * 0.5 + 0.1;
198         self.checkattack                = GenericCheckAttack;
199         self.attack_melee               = spider_attack_standing;
200         self.attack_ranged              = spider_attack_ranged;
201         self.think                              = spider_think;
202         self.sprite_height      = 40;
203         
204         monsters_setframe(spider_anim_idle);
205         
206         monster_setupsounds("spider");
207         
208         if not(self.spider_type)
209                 self.spider_type = autocvar_g_monster_spider_attack_type;
210         
211         monster_hook_spawn(); // for post-spawn mods
212 }
213
214 void spawnfunc_monster_spider() 
215 {
216         if not(autocvar_g_monster_spider) { remove(self); return; }
217         
218         self.monster_spawnfunc = spawnfunc_monster_spider;
219         
220         if(Monster_CheckAppearFlags(self))
221                 return;
222         
223         if not (monster_initialize(
224                          "Spider", MONSTER_SPIDER,
225                          SPIDER_MIN, SPIDER_MAX,
226                          FALSE,
227                          spider_die, spider_spawn))
228         {
229                 remove(self);
230                 return;
231         }
232 }
233
234 #endif // SVQC