1 /*-------------------------------------------------------------------------------
2
3 BARONY
4 File: actsink.cpp
5 Desc: behavior function for sinks
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 "monster.hpp"
17 #include "sound.hpp"
18 #include "items.hpp"
19 #include "net.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 -------------------------------------------------------------------------------*/
32
33 #define SINK_AMBIENCE my->skill[7]
34 #define SINK_DISABLE_POLYMORPH_WASHING my->skill[8]
35
actSink(Entity * my)36 void actSink(Entity* my)
37 {
38 SINK_AMBIENCE--;
39 if ( SINK_AMBIENCE <= 0 )
40 {
41 SINK_AMBIENCE = TICKS_PER_SECOND * 30;
42 playSoundEntityLocal( my, 149, 32 );
43 }
44
45 if ( my->skill[2] > 0 )
46 {
47 Entity* entity = spawnGib(my);
48 entity->flags[INVISIBLE] = false;
49 entity->x += .5;
50 entity->z -= 3;
51 entity->flags[SPRITE] = false;
52 entity->flags[NOUPDATE] = true;
53 entity->flags[UPDATENEEDED] = false;
54 entity->skill[4] = 6;
55 entity->sprite = 4;
56 entity->yaw = (rand() % 360) * PI / 180.0;
57 entity->pitch = (rand() % 360) * PI / 180.0;
58 entity->roll = (rand() % 360) * PI / 180.0;
59 entity->vel_x = 0;
60 entity->vel_y = 0;
61 entity->vel_z = .25;
62 entity->fskill[3] = 0.03;
63
64 if ( multiplayer != CLIENT )
65 {
66 my->skill[2]--;
67 }
68 }
69
70 if ( multiplayer == CLIENT )
71 {
72 return;
73 }
74
75 //Using the sink. //TODO: Monsters using it?
76 int i;
77 for (i = 0; i < MAXPLAYERS; ++i)
78 {
79 if ( (i == 0 && selectedEntity == my) || (client_selected[i] == my) )
80 {
81 if (inrange[i])
82 {
83 //First check that it's not depleted.
84 if (my->skill[0] == 0)
85 {
86 messagePlayer(i, language[580]);
87 playSoundEntity(my, 140 + rand() % 2, 64);
88 }
89 else
90 {
91 if ( players[i]->entity->flags[BURNING] )
92 {
93 messagePlayer(i, language[468]);
94 players[i]->entity->flags[BURNING] = false;
95 serverUpdateEntityFlag(players[i]->entity, BURNING);
96 steamAchievementClient(i, "BARONY_ACH_HOT_SHOWER");
97 }
98 if ( stats[i] && stats[i]->EFFECTS[EFF_POLYMORPH] && (SINK_DISABLE_POLYMORPH_WASHING == 0) )
99 {
100 if ( stats[i]->EFFECTS[EFF_POLYMORPH] )
101 {
102 players[i]->entity->setEffect(EFF_POLYMORPH, false, 0, true);
103 players[i]->entity->effectPolymorph = 0;
104 serverUpdateEntitySkill(players[i]->entity, 50);
105 messagePlayer(i, language[3192]);
106 messagePlayer(i, language[3185]);
107 }
108 /*if ( stats[i]->EFFECTS[EFF_SHAPESHIFT] )
109 {
110 players[i]->entity->setEffect(EFF_SHAPESHIFT, false, 0, true);
111 players[i]->entity->effectShapeshift = 0;
112 serverUpdateEntitySkill(players[i]->entity, 53);
113 messagePlayer(i, language[3418]);
114 messagePlayer(i, language[3417]);
115 }*/
116
117 playSoundEntity(players[i]->entity, 400, 92);
118 createParticleDropRising(players[i]->entity, 593, 1.f);
119 serverSpawnMiscParticles(players[i]->entity, PARTICLE_EFFECT_RISING_DROP, 593);
120 }
121 switch (my->skill[3])
122 {
123 case 0:
124 {
125 //playSoundEntity(players[i]->entity, 52, 64);
126 messagePlayer(i, language[581]);
127
128 //Randomly choose a ring.
129 //88-99 are rings.
130 //So 12 rings total.
131 int ring = rand() % 12 + (int)(RING_ADORNMENT); //Generate random number between 0 & 11, then add 88 to it so that it's at the location of the rings.
132
133 //Generate a random status.
134 Status status = SERVICABLE;
135 int status_rand = rand() % 4;
136 switch (status_rand)
137 {
138 case 0:
139 status = DECREPIT;
140 break;
141 case 1:
142 status = WORN;
143 break;
144 case 2:
145 status = SERVICABLE;
146 break;
147 case 3:
148 status = EXCELLENT;
149 break;
150 default:
151 status = SERVICABLE;
152 break;
153 }
154 //Random beatitude (third parameter).
155 int beatitude = rand() % 5 - 2; //No item will be able to generate with less than -2 or more than +2 beatitude
156
157 //Actually create the item, put it in the player's inventory, and then free the memory of the temp item.
158 Item* item = newItem(static_cast<ItemType>(ring), static_cast<Status>(status), beatitude, 1, rand(), false, NULL);
159 if (item)
160 {
161 itemPickup(i, item);
162 messagePlayer(i, language[504], item->description());
163 free(item);
164 }
165 break;
166 }
167 case 1:
168 {
169 //playSoundEntity(players[i]->entity, 52, 64);
170
171 // spawn slime
172 Entity* monster = summonMonster(SLIME, my->x, my->y);
173 if ( monster )
174 {
175 Uint32 color = SDL_MapRGB(mainsurface->format, 255, 128, 0);
176 messagePlayerColor(i, color, language[582]);
177 Stat* monsterStats = monster->getStats();
178 monsterStats->LVL = 4;
179 monster->sprite = 210;
180 monster->flags[INVISIBLE] = false;
181 }
182 break;
183 }
184 case 2:
185 {
186 if ( stats[i]->type == AUTOMATON )
187 {
188 Uint32 color = SDL_MapRGB(mainsurface->format, 255, 128, 0);
189 messagePlayerColor(i, color, language[3700]);
190 playSoundEntity(players[i]->entity, 52, 64);
191 stats[i]->HUNGER -= 200; //Lose boiler
192 players[i]->entity->modMP(5 + rand() % 6); //Raise temperature because steam.
193 serverUpdateHunger(i);
194 }
195 else if ( stats[i]->type != VAMPIRE )
196 {
197 messagePlayer(i, language[583]);
198 playSoundEntity(players[i]->entity, 52, 64);
199 stats[i]->HUNGER += 50; //Less nutrition than the refreshing fountain.
200 players[i]->entity->modHP(1);
201 }
202 else
203 {
204 players[i]->entity->modHP(-2);
205 playSoundEntity(players[i]->entity, 28, 64);
206 playSoundEntity(players[i]->entity, 249, 128);
207 players[i]->entity->setObituary(language[1533]);
208
209 Uint32 color = SDL_MapRGB(mainsurface->format, 255, 0, 0);
210 messagePlayerColor(i, color, language[3183]);
211 if ( i == 0 || splitscreen )
212 {
213 cameravars[i].shakex += .1;
214 cameravars[i].shakey += 10;
215 }
216 else if ( multiplayer == SERVER && i > 0 )
217 {
218 strcpy((char*)net_packet->data, "SHAK");
219 net_packet->data[4] = 10; // turns into .1
220 net_packet->data[5] = 10;
221 net_packet->address.host = net_clients[i - 1].host;
222 net_packet->address.port = net_clients[i - 1].port;
223 net_packet->len = 6;
224 sendPacketSafe(net_sock, -1, net_packet, i - 1);
225 }
226 }
227 break;
228 }
229 case 3:
230 {
231 if ( stats[i]->type == AUTOMATON )
232 {
233 Uint32 color = SDL_MapRGB(mainsurface->format, 255, 128, 0);
234 messagePlayerColor(i, color, language[3701]);
235 playSoundEntity(players[i]->entity, 52, 64);
236 stats[i]->HUNGER += 200; //Gain boiler
237 players[i]->entity->modMP(2);
238 serverUpdateHunger(i);
239 break;
240 }
241 else
242 {
243 if ( stats[i]->type != VAMPIRE )
244 {
245 players[i]->entity->modHP(-2);
246 }
247 else
248 {
249 players[i]->entity->modHP(-2);
250 playSoundEntity(players[i]->entity, 249, 128);
251 }
252 playSoundEntity(players[i]->entity, 28, 64);
253 players[i]->entity->setObituary(language[1533]);
254
255 Uint32 color = SDL_MapRGB(mainsurface->format, 255, 0, 0);
256 messagePlayerColor(i, color, language[584]);
257
258 if ( i == 0 || splitscreen )
259 {
260 cameravars[i].shakex += .1;
261 cameravars[i].shakey += 10;
262 }
263 else if ( multiplayer == SERVER && i > 0 )
264 {
265 strcpy((char*)net_packet->data, "SHAK");
266 net_packet->data[4] = 10; // turns into .1
267 net_packet->data[5] = 10;
268 net_packet->address.host = net_clients[i - 1].host;
269 net_packet->address.port = net_clients[i - 1].port;
270 net_packet->len = 6;
271 sendPacketSafe(net_sock, -1, net_packet, i - 1);
272 }
273 }
274 break;
275 }
276 default:
277 break;
278 }
279
280 // run the water particles
281 my->skill[2] = TICKS_PER_SECOND / 2;
282
283 //Deduct one usage from it.
284 if (my->skill[0] > 1) //First usage. Will create second stats now.
285 {
286 my->skill[0]--; //Deduct one usage.
287
288 //Randomly choose second usage stats.
289 int effect = rand() % 10; //4 possible effects.
290 switch (effect)
291 {
292 case 0:
293 //10% chance.
294 my->skill[3] = 0; //Player will find a ring.
295 case 1:
296 //10% chance.
297 my->skill[3] = 1; //Will spawn a slime.
298 break;
299 case 2:
300 case 3:
301 case 4:
302 case 5:
303 case 6:
304 case 7:
305 //60% chance.
306 my->skill[3] = 2; //Will raise nutrition.
307 break;
308 case 8:
309 case 9:
310 //20% chance.
311 my->skill[3] = 3; //Player will lose 1 HP.
312 break;
313 default:
314 break; //Should never happen.
315 }
316 }
317 else //Second usage.
318 {
319 my->skill[0]--; //Sink is depleted!
320 messagePlayer(i, language[585]);
321 playSoundEntity(my, 132, 64);
322 }
323 serverUpdateEntitySkill(my, 0);
324 }
325 }
326 }
327 }
328 }
329