1 /*-------------------------------------------------------------------------------
2
3 BARONY
4 File: actgib.cpp
5 Desc: behavior function for gibs
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 "monster.hpp"
16 #include "entity.hpp"
17 #include "net.hpp"
18 #include "collision.hpp"
19 #include "player.hpp"
20
21 /*-------------------------------------------------------------------------------
22
23 act*
24
25 The following function describes an entity behavior. The function
26 takes a pointer to the entity that uses it as an argument.
27
28 -------------------------------------------------------------------------------*/
29
30 #define GIB_VELX my->vel_x
31 #define GIB_VELY my->vel_y
32 #define GIB_VELZ my->vel_z
33 #define GIB_GRAVITY my->fskill[3]
34 #define GIB_LIFESPAN my->skill[4]
35
actGib(Entity * my)36 void actGib(Entity* my)
37 {
38 // don't update gibs that have no velocity
39 if ( my->z == 8 && fabs(GIB_VELX) < .01 && fabs(GIB_VELY) < .01 )
40 {
41 list_RemoveNode(my->mynode);
42 return;
43 }
44
45 // remove gibs that have exceeded their life span
46 if ( my->ticks > GIB_LIFESPAN && GIB_LIFESPAN )
47 {
48 list_RemoveNode(my->mynode);
49 return;
50 }
51
52 if ( my->flags[OVERDRAW]
53 && players[clientnum] && players[clientnum]->entity && players[clientnum]->entity->skill[3] == 1 )
54 {
55 // debug cam, don't draw overdrawn.
56 my->flags[INVISIBLE] = true;
57 }
58
59 // horizontal motion
60 my->yaw += sqrt(GIB_VELX * GIB_VELX + GIB_VELY * GIB_VELY) * .05;
61 my->x += GIB_VELX;
62 my->y += GIB_VELY;
63 GIB_VELX = GIB_VELX * .95;
64 GIB_VELY = GIB_VELY * .95;
65
66 // gravity
67 if ( my->z < 8 )
68 {
69 GIB_VELZ += GIB_GRAVITY;
70 my->z += GIB_VELZ;
71 my->roll += 0.1;
72 }
73 else
74 {
75 if ( my->x >= 0 && my->y >= 0 && my->x < map.width << 4 && my->y < map.height << 4 )
76 {
77 if ( !map.tiles[(int)(floor(my->y / 16)*MAPLAYERS + floor(my->x / 16)*MAPLAYERS * map.height)] )
78 {
79 GIB_VELZ += GIB_GRAVITY;
80 my->z += GIB_VELZ;
81 my->roll += 0.1;
82 }
83 else
84 {
85 GIB_VELZ = 0;
86 my->z = 8;
87 my->roll = PI / 2.0;
88 }
89 }
90 else
91 {
92 GIB_VELZ += GIB_GRAVITY;
93 my->z += GIB_VELZ;
94 my->roll += 0.1;
95 }
96 }
97
98 // gibs disappear after falling to a certain point
99 if ( my->z > 128 )
100 {
101 list_RemoveNode(my->mynode);
102 return;
103 }
104 }
105
106 /*-------------------------------------------------------------------------------
107
108 spawnGib
109
110 Spawns a gib with a random velocity for the entity supplied as an
111 argument
112
113 -------------------------------------------------------------------------------*/
114
spawnGib(Entity * parentent,int customGibSprite)115 Entity* spawnGib(Entity* parentent, int customGibSprite)
116 {
117 Entity* entity = nullptr;
118 Stat* parentstats = nullptr;
119 double vel;
120 int gibsprite = 5;
121
122 if ( !parentent )
123 {
124 return nullptr;
125 }
126
127 if ( (parentstats = parentent->getStats()) != nullptr )
128 {
129 if ( multiplayer == CLIENT )
130 {
131 printlog("[%s:%d spawnGib()] spawnGib() called on client, got clientstats. Probably bad?", __FILE__, __LINE__);
132 }
133
134 if ( customGibSprite != -1 )
135 {
136 gibsprite = customGibSprite;
137 }
138 else
139 {
140 switch ( gibtype[(int)parentstats->type] )
141 {
142 case 0:
143 return nullptr;
144 case 1:
145 gibsprite = 5;
146 break;
147 case 2:
148 gibsprite = 211;
149 break;
150 case 3:
151 if ( parentent->sprite == 210 )
152 {
153 gibsprite = 211;
154 }
155 else
156 {
157 gibsprite = 215;
158 }
159 break;
160 case 4:
161 gibsprite = 683;
162 break;
163 //TODO: Gear gibs for automatons, and crystal gibs for golem.
164 default:
165 gibsprite = 5;
166 break;
167 }
168 }
169 }
170 else if ( parentent->behavior == &actThrown )
171 {
172 if ( customGibSprite != -1 )
173 {
174 gibsprite = customGibSprite;
175 }
176 }
177
178 entity = newEntity(gibsprite, 1, map.entities, nullptr); //Gib entity.
179 if ( !entity )
180 {
181 return nullptr;
182 }
183 entity->x = parentent->x;
184 entity->y = parentent->y;
185 entity->z = parentent->z;
186 entity->parent = parentent->getUID();
187 entity->sizex = 2;
188 entity->sizey = 2;
189 entity->yaw = (rand() % 360) * PI / 180.0;
190 entity->pitch = (rand() % 360) * PI / 180.0;
191 entity->roll = (rand() % 360) * PI / 180.0;
192 vel = (rand() % 10) / 10.f;
193 entity->vel_x = vel * cos(entity->yaw);
194 entity->vel_y = vel * sin(entity->yaw);
195 entity->vel_z = -.5;
196 entity->fskill[3] = 0.04;
197 entity->behavior = &actGib;
198 entity->flags[PASSABLE] = true;
199 entity->flags[NOUPDATE] = true;
200 entity->flags[UNCLICKABLE] = true;
201 if ( !spawn_blood && customGibSprite == -1 )
202 {
203 entity->flags[INVISIBLE] = true;
204 }
205 if ( multiplayer != CLIENT )
206 {
207 entity_uids--;
208 }
209 entity->setUID(-3);
210
211 return entity;
212 }
213
spawnGibClient(Sint16 x,Sint16 y,Sint16 z,Sint16 sprite)214 Entity* spawnGibClient(Sint16 x, Sint16 y, Sint16 z, Sint16 sprite)
215 {
216 double vel;
217
218 Entity* entity = newEntity(sprite, 1, map.entities, nullptr); //Gib entity.
219 entity->x = x;
220 entity->y = y;
221 entity->z = z;
222 entity->sizex = 2;
223 entity->sizey = 2;
224 entity->yaw = (rand() % 360) * PI / 180.0;
225 entity->pitch = (rand() % 360) * PI / 180.0;
226 entity->roll = (rand() % 360) * PI / 180.0;
227 vel = (rand() % 10) / 10.f;
228 entity->vel_x = vel * cos(entity->yaw);
229 entity->vel_y = vel * sin(entity->yaw);
230 entity->vel_z = -.5;
231 entity->fskill[3] = 0.04;
232 entity->behavior = &actGib;
233 entity->flags[PASSABLE] = true;
234 entity->flags[NOUPDATE] = true;
235 entity->flags[UNCLICKABLE] = true;
236
237 return entity;
238 }
239
serverSpawnGibForClient(Entity * gib)240 void serverSpawnGibForClient(Entity* gib)
241 {
242 int c;
243 if ( !gib )
244 {
245 return;
246 }
247 if ( multiplayer == SERVER )
248 {
249 for ( c = 1; c < MAXPLAYERS; c++ )
250 {
251 if ( client_disconnected[c] )
252 {
253 continue;
254 }
255 strcpy((char*)net_packet->data, "SPGB");
256 SDLNet_Write16((Sint16)gib->x, &net_packet->data[4]);
257 SDLNet_Write16((Sint16)gib->y, &net_packet->data[6]);
258 SDLNet_Write16((Sint16)gib->z, &net_packet->data[8]);
259 SDLNet_Write16((Sint16)gib->sprite, &net_packet->data[10]);
260 net_packet->data[12] = gib->flags[SPRITE];
261 net_packet->address.host = net_clients[c - 1].host;
262 net_packet->address.port = net_clients[c - 1].port;
263 net_packet->len = 13;
264 sendPacketSafe(net_sock, -1, net_packet, c - 1);
265 }
266 }
267 }
268