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