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