1 /*-------------------------------------------------------------------------------
2
3 BARONY
4 File: actmagictrap.cpp
5 Desc: implements magic trap code
6
7 Copyright 2013-2016 (c) Turning Wheel LLC, all rights reserved.
8 See LICENSE for details.
9
10 -------------------------------------------------------------------------------*/
11
12 #include "main.hpp"
13 #include "game.hpp"
14 #include "stat.hpp"
15 #include "entity.hpp"
16 #include "sound.hpp"
17 #include "items.hpp"
18 #include "net.hpp"
19 #include "monster.hpp"
20 #include "collision.hpp"
21 #include "player.hpp"
22 #include "magic/magic.hpp"
23
24 /*-------------------------------------------------------------------------------
25
26 act*
27
28 The following function describes an entity behavior. The function
29 takes a pointer to the entity that uses it as an argument.
30
31 -------------------------------------------------------------------------------*/
actMagicTrapCeiling(Entity * my)32 void actMagicTrapCeiling(Entity* my)
33 {
34 if ( !my )
35 {
36 return;
37 }
38
39 my->actMagicTrapCeiling();
40 }
41
42
actMagicTrapCeiling()43 void Entity::actMagicTrapCeiling()
44 {
45 spellTrapAmbience--;
46 if ( spellTrapAmbience <= 0 )
47 {
48 spellTrapAmbience = TICKS_PER_SECOND * 30;
49 playSoundEntity(this, 149, 16);
50 }
51
52 if ( multiplayer == CLIENT )
53 {
54 return;
55 }
56 if ( circuit_status != CIRCUIT_ON )
57 {
58 spellTrapReset = 0;
59 spellTrapCounter = spellTrapRefireRate; //shoost instantly!
60 return;
61 }
62
63 if ( !spellTrapInit )
64 {
65 spellTrapInit = 1;
66 if ( spellTrapType == -1 )
67 {
68 switch ( rand() % 8 )
69 {
70 case 0:
71 spellTrapType = SPELL_FORCEBOLT;
72 break;
73 case 1:
74 spellTrapType = SPELL_MAGICMISSILE;
75 break;
76 case 2:
77 spellTrapType = SPELL_COLD;
78 break;
79 case 3:
80 spellTrapType = SPELL_FIREBALL;
81 break;
82 case 4:
83 spellTrapType = SPELL_LIGHTNING;
84 break;
85 case 5:
86 spellTrapType = SPELL_SLEEP;
87 spellTrapRefireRate = 275; // stop getting stuck forever!
88 break;
89 case 6:
90 spellTrapType = SPELL_CONFUSE;
91 break;
92 case 7:
93 spellTrapType = SPELL_SLOW;
94 break;
95 default:
96 spellTrapType = SPELL_MAGICMISSILE;
97 break;
98 }
99 }
100 //light = lightSphere(my->x / 16, my->y / 16, 3, 192);
101 }
102
103 ++spellTrapCounter;
104
105 node_t* node = children.first;
106 Entity* ceilingModel = (Entity*)(node->element);
107 int triggerSprite = 0;
108 switch ( spellTrapType )
109 {
110 case SPELL_FORCEBOLT:
111 case SPELL_MAGICMISSILE:
112 case SPELL_CONFUSE:
113 triggerSprite = 173;
114 break;
115 case SPELL_FIREBALL:
116 triggerSprite = 168;
117 break;
118 case SPELL_LIGHTNING:
119 triggerSprite = 170;
120 break;
121 case SPELL_COLD:
122 case SPELL_SLEEP:
123 triggerSprite = 172;
124 break;
125 case SPELL_SLOW:
126 default:
127 triggerSprite = 171;
128 break;
129 }
130
131 if ( spellTrapCounter > spellTrapRefireRate )
132 {
133 spellTrapCounter = 0; // reset timer.
134 if ( spellTrapReset == 0 )
135 {
136 // once off magic particles. reset once power is cut.
137 spawnMagicEffectParticles(x, y, z, triggerSprite);
138 playSoundEntity(this, 252, 128);
139 spellTrapReset = 1;
140 /*spellTrapCounter = spellTrapRefireRate - 5; // delay?
141 return;*/
142 }
143 Entity* entity = castSpell(getUID(), getSpellFromID(spellTrapType), false, true);
144 if ( ceilingModel && entity )
145 {
146 entity->x = x;
147 entity->y = y;
148 entity->z = ceilingModel->z - 2;
149 double missile_speed = 4 * ((double)(((spellElement_t*)(getSpellFromID(spellTrapType)->elements.first->element))->mana) / ((spellElement_t*)(getSpellFromID(spellTrapType)->elements.first->element))->overload_multiplier);
150 entity->vel_x = 0.0;
151 entity->vel_y = 0.0;
152 entity->vel_z = 0.5 * (missile_speed);
153 entity->pitch = PI / 2;
154 entity->actmagicIsVertical = MAGIC_ISVERTICAL_Z;
155 }
156 }
157 }
158
159 /*-------------------------------------------------------------------------------
160
161 act*
162
163 The following function describes an entity behavior. The function
164 takes a pointer to the entity that uses it as an argument.
165
166 -------------------------------------------------------------------------------*/
167
168 #define MAGICTRAP_INIT my->skill[0]
169 #define MAGICTRAP_SPELL my->skill[1]
170 #define MAGICTRAP_DIRECTION my->skill[3]
171
actMagicTrap(Entity * my)172 void actMagicTrap(Entity* my)
173 {
174 if ( !MAGICTRAP_INIT )
175 {
176 MAGICTRAP_INIT = 1;
177 switch ( rand() % 8 )
178 {
179 case 0:
180 MAGICTRAP_SPELL = SPELL_FORCEBOLT;
181 break;
182 case 1:
183 MAGICTRAP_SPELL = SPELL_MAGICMISSILE;
184 break;
185 case 2:
186 MAGICTRAP_SPELL = SPELL_COLD;
187 break;
188 case 3:
189 MAGICTRAP_SPELL = SPELL_FIREBALL;
190 break;
191 case 4:
192 MAGICTRAP_SPELL = SPELL_LIGHTNING;
193 break;
194 case 5:
195 MAGICTRAP_SPELL = SPELL_SLEEP;
196 break;
197 case 6:
198 MAGICTRAP_SPELL = SPELL_CONFUSE;
199 break;
200 case 7:
201 MAGICTRAP_SPELL = SPELL_SLOW;
202 break;
203 default:
204 MAGICTRAP_SPELL = SPELL_MAGICMISSILE;
205 break;
206 }
207 my->light = lightSphere(my->x / 16, my->y / 16, 3, 192);
208 }
209
210 // eliminate traps that have been destroyed.
211 // check wall inside me.
212 int checkx = static_cast<int>(my->x) >> 4;
213 int checky = static_cast<int>(my->y) >> 4;
214 if ( !map.tiles[OBSTACLELAYER + checky * MAPLAYERS + checkx * MAPLAYERS * map.height] ) // wall
215 {
216 my->removeLightField();
217 list_RemoveNode(my->mynode);
218 return;
219 }
220
221 if ( multiplayer == CLIENT )
222 {
223 return;
224 }
225
226 if ( my->ticks % TICKS_PER_SECOND == 0 )
227 {
228 int oldir = 0;
229 int x = 0, y = 0;
230 switch ( MAGICTRAP_DIRECTION )
231 {
232 case 0:
233 x = 12;
234 y = 0;
235 oldir = MAGICTRAP_DIRECTION;
236 MAGICTRAP_DIRECTION++;
237 break;
238 case 1:
239 x = 0;
240 y = 12;
241 oldir = MAGICTRAP_DIRECTION;
242 MAGICTRAP_DIRECTION++;
243 break;
244 case 2:
245 x = -12;
246 y = 0;
247 oldir = MAGICTRAP_DIRECTION;
248 MAGICTRAP_DIRECTION++;
249 break;
250 case 3:
251 x = 0;
252 y = -12;
253 oldir = MAGICTRAP_DIRECTION;
254 MAGICTRAP_DIRECTION = 0;
255 break;
256 }
257 int u = std::min<int>(std::max<int>(0.0, (my->x + x) / 16), map.width - 1);
258 int v = std::min<int>(std::max<int>(0.0, (my->y + y) / 16), map.height - 1);
259 if ( !map.tiles[OBSTACLELAYER + v * MAPLAYERS + u * MAPLAYERS * map.height] )
260 {
261 Entity* entity = castSpell(my->getUID(), getSpellFromID(MAGICTRAP_SPELL), false, true);
262 entity->x = my->x + x;
263 entity->y = my->y + y;
264 entity->z = my->z;
265 entity->yaw = oldir * (PI / 2.f);
266 double missile_speed = 4 * ((double)(((spellElement_t*)(getSpellFromID(MAGICTRAP_SPELL)->elements.first->element))->mana) / ((spellElement_t*)(getSpellFromID(MAGICTRAP_SPELL)->elements.first->element))->overload_multiplier);
267 entity->vel_x = cos(entity->yaw) * (missile_speed);
268 entity->vel_y = sin(entity->yaw) * (missile_speed);
269 }
270 }
271 }