~ubuntu-branches/debian/stretch/opentyrian/stretch

« back to all changes in this revision

Viewing changes to src/shots.c

  • Committer: Package Import Robot
  • Author(s): Etienne Millon
  • Date: 2015-03-31 08:48:54 UTC
  • Revision ID: package-import@ubuntu.com-20150331084854-f5a4uoz7uv3vopk6
Tags: upstream-2.1.20130907+dfsg
ImportĀ upstreamĀ versionĀ 2.1.20130907+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * OpenTyrian: A modern cross-platform port of Tyrian
 
3
 * Copyright (C) 2007-2013  The OpenTyrian Development Team
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public License
 
7
 * as published by the Free Software Foundation; either version 2
 
8
 * of the License, or (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
18
 */
 
19
#include "player.h"
 
20
#include "shots.h"
 
21
#include "sprite.h"
 
22
#include "video.h"
 
23
#include "varz.h"
 
24
 
 
25
// I'm pretty sure the last extra entry is never used.
 
26
PlayerShotDataType playerShotData[MAX_PWEAPON + 1]; /* [1..MaxPWeapon+1] */
 
27
JE_byte shotAvail[MAX_PWEAPON]; /* [1..MaxPWeapon] */   /*0:Avail 1-255:Duration left*/
 
28
 
 
29
void simulate_player_shots( void )
 
30
{
 
31
        /* Player Shot Images */
 
32
        for (int z = 0; z < MAX_PWEAPON; z++)
 
33
        {
 
34
                if (shotAvail[z] != 0)
 
35
                {
 
36
                        shotAvail[z]--;
 
37
                        if (z != MAX_PWEAPON - 1)
 
38
                        {
 
39
                                PlayerShotDataType* shot = &playerShotData[z];
 
40
 
 
41
                                shot->shotXM += shot->shotXC;
 
42
 
 
43
                                if (shot->shotXM <= 100)
 
44
                                        shot->shotX += shot->shotXM;
 
45
 
 
46
                                shot->shotYM += shot->shotYC;
 
47
                                shot->shotY += shot->shotYM;
 
48
 
 
49
                                if (shot->shotYM > 100)
 
50
                                {
 
51
                                        shot->shotY -= 120;
 
52
                                        shot->shotY += player[0].delta_y_shot_move;
 
53
                                }
 
54
 
 
55
                                if (shot->shotComplicated != 0)
 
56
                                {
 
57
                                        shot->shotDevX += shot->shotDirX;
 
58
                                        shot->shotX += shot->shotDevX;
 
59
 
 
60
                                        if (abs(shot->shotDevX) == shot->shotCirSizeX)
 
61
                                                shot->shotDirX = -shot->shotDirX;
 
62
 
 
63
                                        shot->shotDevY += shot->shotDirY;
 
64
                                        shot->shotY += shot->shotDevY;
 
65
 
 
66
                                        if (abs(shot->shotDevY) == shot->shotCirSizeY)
 
67
                                                shot->shotDirY = -shot->shotDirY;
 
68
                                        /*Double Speed Circle Shots - add a second copy of above loop*/
 
69
                                }
 
70
 
 
71
                                int tempShotX = shot->shotX;
 
72
                                int tempShotY = shot->shotY;
 
73
 
 
74
                                if (shot->shotX < 0 || shot->shotX > 140 ||
 
75
                                    shot->shotY < 0 || shot->shotY > 170)
 
76
                                {
 
77
                                        shotAvail[z] = 0;
 
78
                                        goto draw_player_shot_loop_end;
 
79
                                }
 
80
 
 
81
/*                              if (shot->shotTrail != 255)
 
82
                                {
 
83
                                        if (shot->shotTrail == 98)
 
84
                                        {
 
85
                                                JE_setupExplosion(shot->shotX - shot->shotXM, shot->shotY - shot->shotYM, shot->shotTrail);
 
86
                                        } else {
 
87
                                                JE_setupExplosion(shot->shotX, shot->shotY, shot->shotTrail);
 
88
                                        }
 
89
                                }*/
 
90
 
 
91
                                JE_word anim_frame = shot->shotGr + shot->shotAni;
 
92
                                if (++shot->shotAni == shot->shotAniMax)
 
93
                                        shot->shotAni = 0;
 
94
 
 
95
                                if (anim_frame < 6000)
 
96
                                {
 
97
                                        if (anim_frame > 1000)
 
98
                                                anim_frame = anim_frame % 1000;
 
99
                                        if (anim_frame > 500)
 
100
                                                blit_sprite2(VGAScreen, tempShotX+1, tempShotY, shapesW2, anim_frame - 500);
 
101
                                        else
 
102
                                                blit_sprite2(VGAScreen, tempShotX+1, tempShotY, shapesC1, anim_frame);
 
103
                                }
 
104
                        }
 
105
 
 
106
draw_player_shot_loop_end:
 
107
                        ;
 
108
                }
 
109
        }
 
110
}
 
111
 
 
112
static const JE_word linkMultiGr[17] /* [0..16] */ =
 
113
        {77,221,183,301,1,282,164,202,58,201,163,281,39,300,182,220,77};
 
114
static const JE_word linkSonicGr[17] /* [0..16] */ =
 
115
        {85,242,131,303,47,284,150,223,66,224,149,283,9,302,130,243,85};
 
116
static const JE_word linkMult2Gr[17] /* [0..16] */ =
 
117
        {78,299,295,297,2,278,276,280,59,279,275,277,40,296,294,298,78};
 
118
 
 
119
void player_shot_set_direction( JE_integer shot_id, uint weapon_id, JE_real direction )
 
120
{
 
121
        PlayerShotDataType* shot = &playerShotData[shot_id];
 
122
 
 
123
        shot->shotXM = -roundf(sinf(direction) * shot->shotYM);
 
124
        shot->shotYM = -roundf(cosf(direction) * shot->shotYM);
 
125
 
 
126
        // Some weapons have sprites for each direction, use those.
 
127
        int rounded_dir;
 
128
 
 
129
        switch (weapon_id)
 
130
        {
 
131
        case 27:
 
132
        case 32:
 
133
        case 10:
 
134
                rounded_dir = roundf(direction * (16 / (2 * M_PI)));  /*16 directions*/
 
135
                shot->shotGr = linkMultiGr[rounded_dir];
 
136
                break;
 
137
        case 28:
 
138
        case 33:
 
139
        case 11:
 
140
                rounded_dir = roundf(direction * (16 / (2 * M_PI)));  /*16 directions*/
 
141
                shot->shotGr = linkSonicGr[rounded_dir];
 
142
                break;
 
143
        case 30:
 
144
        case 35:
 
145
        case 14:
 
146
                if (direction > M_PI_2 && direction < M_PI + M_PI_2)
 
147
                {
 
148
                        shot->shotYC = 1;
 
149
                }
 
150
                break;
 
151
        case 38:
 
152
        case 22:
 
153
                rounded_dir = roundf(direction * (16 / (2 * M_PI)));  /*16 directions*/
 
154
                shot->shotGr = linkMult2Gr[rounded_dir];
 
155
                break;
 
156
        }
 
157
}
 
158
 
 
159
bool player_shot_move_and_draw(
 
160
                int shot_id, bool* out_is_special,
 
161
                int* out_shotx, int* out_shoty,
 
162
                JE_integer* out_shot_damage, JE_byte* out_blast_filter,
 
163
                JE_byte* out_chain, JE_byte* out_playerNum,
 
164
                JE_word* out_special_radiusw, JE_word* out_special_radiush )
 
165
{
 
166
        PlayerShotDataType* shot = &playerShotData[shot_id];
 
167
 
 
168
        shotAvail[shot_id]--;
 
169
        if (shot_id != MAX_PWEAPON - 1)
 
170
        {
 
171
                shot->shotXM += shot->shotXC;
 
172
                shot->shotX += shot->shotXM;
 
173
                JE_integer tmp_shotXM = shot->shotXM;
 
174
 
 
175
                if (shot->shotXM > 100)
 
176
                {
 
177
                        if (shot->shotXM == 101)
 
178
                        {
 
179
                                shot->shotX -= 101;
 
180
                                shot->shotX += player[shot->playerNumber-1].delta_x_shot_move;
 
181
                                shot->shotY += player[shot->playerNumber-1].delta_y_shot_move;
 
182
                        }
 
183
                        else
 
184
                        {
 
185
                                shot->shotX -= 120;
 
186
                                shot->shotX += player[shot->playerNumber-1].delta_x_shot_move;
 
187
                        }
 
188
                }
 
189
 
 
190
                shot->shotYM += shot->shotYC;
 
191
                shot->shotY += shot->shotYM;
 
192
 
 
193
                if (shot->shotYM > 100)
 
194
                {
 
195
                        shot->shotY -= 120;
 
196
                        shot->shotY += player[shot->playerNumber-1].delta_y_shot_move;
 
197
                }
 
198
 
 
199
                if (shot->shotComplicated != 0)
 
200
                {
 
201
                        shot->shotDevX += shot->shotDirX;
 
202
                        shot->shotX += shot->shotDevX;
 
203
 
 
204
                        if (abs(shot->shotDevX) == shot->shotCirSizeX)
 
205
                                shot->shotDirX = -shot->shotDirX;
 
206
 
 
207
                        shot->shotDevY += shot->shotDirY;
 
208
                        shot->shotY += shot->shotDevY;
 
209
 
 
210
                        if (abs(shot->shotDevY) == shot->shotCirSizeY)
 
211
                                shot->shotDirY = -shot->shotDirY;
 
212
 
 
213
                        /*Double Speed Circle Shots - add a second copy of above loop*/
 
214
                }
 
215
 
 
216
                *out_shotx = shot->shotX;
 
217
                *out_shoty = shot->shotY;
 
218
 
 
219
                if (shot->shotX < -34 || shot->shotX > 290 ||
 
220
                        shot->shotY < -15 || shot->shotY > 190)
 
221
                {
 
222
                        shotAvail[shot_id] = 0;
 
223
                        return false;
 
224
                }
 
225
 
 
226
                if (shot->shotTrail != 255)
 
227
                {
 
228
                        if (shot->shotTrail == 98)
 
229
                                JE_setupExplosion(shot->shotX - shot->shotXM, shot->shotY - shot->shotYM, 0, shot->shotTrail, false, false);
 
230
                        else
 
231
                                JE_setupExplosion(shot->shotX, shot->shotY, 0, shot->shotTrail, false, false);
 
232
                }
 
233
 
 
234
                if (shot->aimAtEnemy != 0)
 
235
                {
 
236
                        if (--shot->aimDelay == 0)
 
237
                        {
 
238
                                shot->aimDelay = shot->aimDelayMax;
 
239
 
 
240
                                if (enemyAvail[shot->aimAtEnemy - 1] != 1)
 
241
                                {
 
242
                                        if (shot->shotX < enemy[shot->aimAtEnemy - 1].ex)
 
243
                                                shot->shotXM++;
 
244
                                        else
 
245
                                                shot->shotXM--;
 
246
 
 
247
                                        if (shot->shotY < enemy[shot->aimAtEnemy - 1].ey)
 
248
                                                shot->shotYM++;
 
249
                                        else
 
250
                                                shot->shotYM--;
 
251
                                }
 
252
                                else
 
253
                                {
 
254
                                        if (shot->shotXM > 0)
 
255
                                                shot->shotXM++;
 
256
                                        else
 
257
                                                shot->shotXM--;
 
258
                                }
 
259
                        }
 
260
                }
 
261
 
 
262
                JE_word sprite_frame = shot->shotGr + shot->shotAni;
 
263
                if (++shot->shotAni == shot->shotAniMax)
 
264
                        shot->shotAni = 0;
 
265
 
 
266
                *out_shot_damage = shot->shotDmg;
 
267
                *out_blast_filter = shot->shotBlastFilter;
 
268
                *out_chain = shot->chainReaction;
 
269
                *out_playerNum = shot->playerNumber;
 
270
 
 
271
                *out_is_special = sprite_frame > 60000;
 
272
 
 
273
                if (*out_is_special)
 
274
                {
 
275
                        blit_sprite_blend(VGAScreen, *out_shotx+1, *out_shoty, OPTION_SHAPES, sprite_frame - 60001);
 
276
 
 
277
                        *out_special_radiusw = sprite(OPTION_SHAPES, sprite_frame - 60001)->width / 2;
 
278
                        *out_special_radiush = sprite(OPTION_SHAPES, sprite_frame - 60001)->height / 2;
 
279
                }
 
280
                else
 
281
                {
 
282
                        if (sprite_frame > 1000)
 
283
                        {
 
284
                                JE_doSP(*out_shotx+1 + 6, *out_shoty + 6, 5, 3, (sprite_frame / 1000) << 4);
 
285
                                sprite_frame = sprite_frame % 1000;
 
286
                        }
 
287
                        if (sprite_frame > 500)
 
288
                        {
 
289
                                if (background2 && *out_shoty + shadowYDist < 190 && tmp_shotXM < 100)
 
290
                                        blit_sprite2_darken(VGAScreen, *out_shotx+1, *out_shoty + shadowYDist, shapesW2, sprite_frame - 500);
 
291
                                blit_sprite2(VGAScreen, *out_shotx+1, *out_shoty, shapesW2, sprite_frame - 500);
 
292
                        }
 
293
                        else
 
294
                        {
 
295
                                if (background2 && *out_shoty + shadowYDist < 190 && tmp_shotXM < 100)
 
296
                                        blit_sprite2_darken(VGAScreen, *out_shotx+1, *out_shoty + shadowYDist, shapesC1, sprite_frame);
 
297
                                blit_sprite2(VGAScreen, *out_shotx+1, *out_shoty, shapesC1, sprite_frame);
 
298
                        }
 
299
                }
 
300
        }
 
301
 
 
302
        return true;
 
303
}
 
304
 
 
305
JE_integer player_shot_create( JE_word portNum, uint bay_i, JE_word PX, JE_word PY, JE_word mouseX, JE_word mouseY, JE_word wpNum, JE_byte playerNum )
 
306
{
 
307
        static const JE_byte soundChannel[11] /* [1..11] */ = {0, 2, 4, 4, 2, 2, 5, 5, 1, 4, 1};
 
308
 
 
309
        // Bounds check
 
310
        if (portNum > PORT_NUM || wpNum <= 0 || wpNum > WEAP_NUM)
 
311
                return MAX_PWEAPON;
 
312
 
 
313
        const JE_WeaponType* weapon = &weapons[wpNum];
 
314
 
 
315
        if (power < weaponPort[portNum].poweruse)
 
316
                return MAX_PWEAPON;
 
317
        power -= weaponPort[portNum].poweruse;
 
318
 
 
319
        if (weapon->sound > 0)
 
320
                soundQueue[soundChannel[bay_i]] = weapon->sound;
 
321
 
 
322
        int shot_id;
 
323
        /*Rot*/
 
324
        for (int multi_i = 1; multi_i <= weapon->multi; multi_i++)
 
325
        {
 
326
                for (shot_id = 0; shot_id < MAX_PWEAPON; shot_id++)
 
327
                        if (shotAvail[shot_id] == 0)
 
328
                                break;
 
329
                if (shot_id == MAX_PWEAPON)
 
330
                        return MAX_PWEAPON;
 
331
 
 
332
                if (shotMultiPos[bay_i] == weapon->max || shotMultiPos[bay_i] > 8)
 
333
                        shotMultiPos[bay_i] = 1;
 
334
                else
 
335
                        shotMultiPos[bay_i]++;
 
336
 
 
337
                PlayerShotDataType* shot = &playerShotData[shot_id];
 
338
                shot->chainReaction = 0;
 
339
 
 
340
                shot->playerNumber = playerNum;
 
341
 
 
342
                shot->shotAni = 0;
 
343
 
 
344
                shot->shotComplicated = weapon->circlesize != 0;
 
345
 
 
346
                if (weapon->circlesize == 0)
 
347
                {
 
348
                        shot->shotDevX = 0;
 
349
                        shot->shotDirX = 0;
 
350
                        shot->shotDevY = 0;
 
351
                        shot->shotDirY = 0;
 
352
                        shot->shotCirSizeX = 0;
 
353
                        shot->shotCirSizeY = 0;
 
354
                }
 
355
                else
 
356
                {
 
357
                        JE_byte circsize = weapon->circlesize;
 
358
 
 
359
                        if (circsize > 19)
 
360
                        {
 
361
                                JE_byte circsize_mod20 = circsize % 20;
 
362
                                shot->shotCirSizeX = circsize_mod20;
 
363
                                shot->shotDevX = circsize_mod20 >> 1;
 
364
 
 
365
                                circsize = circsize / 20;
 
366
                                shot->shotCirSizeY = circsize;
 
367
                                shot->shotDevY = circsize >> 1;
 
368
                        }
 
369
                        else
 
370
                        {
 
371
                                shot->shotCirSizeX = circsize;
 
372
                                shot->shotCirSizeY = circsize;
 
373
                                shot->shotDevX = circsize >> 1;
 
374
                                shot->shotDevY = circsize >> 1;
 
375
                        }
 
376
                        shot->shotDirX = 1;
 
377
                        shot->shotDirY = -1;
 
378
                }
 
379
 
 
380
                shot->shotTrail = weapon->trail;
 
381
 
 
382
                if (weapon->attack[shotMultiPos[bay_i]-1] > 99 && weapon->attack[shotMultiPos[bay_i]-1] < 250)
 
383
                {
 
384
                        shot->chainReaction = weapon->attack[shotMultiPos[bay_i]-1] - 100;
 
385
                        shot->shotDmg = 1;
 
386
                }
 
387
                else
 
388
                {
 
389
                        shot->shotDmg = weapon->attack[shotMultiPos[bay_i]-1];
 
390
                }
 
391
 
 
392
                shot->shotBlastFilter = weapon->shipblastfilter;
 
393
 
 
394
                JE_integer tmp_by = weapon->by[shotMultiPos[bay_i]-1];
 
395
 
 
396
                /*Note: Only front selection used for player shots...*/
 
397
 
 
398
                shot->shotX = PX + weapon->bx[shotMultiPos[bay_i]-1];
 
399
 
 
400
                shot->shotY = PY + tmp_by;
 
401
                shot->shotYC = -weapon->acceleration;
 
402
                shot->shotXC = weapon->accelerationx;
 
403
 
 
404
                shot->shotXM = weapon->sx[shotMultiPos[bay_i]-1];
 
405
 
 
406
                // Not sure what this field does exactly.
 
407
                JE_byte del = weapon->del[shotMultiPos[bay_i]-1];
 
408
 
 
409
                if (del == 121)
 
410
                {
 
411
                        shot->shotTrail = 0;
 
412
                        del = 255;
 
413
                }
 
414
 
 
415
                shot->shotGr = weapon->sg[shotMultiPos[bay_i]-1];
 
416
                if (shot->shotGr == 0)
 
417
                        shotAvail[shot_id] = 0;
 
418
                else
 
419
                        shotAvail[shot_id] = del;
 
420
 
 
421
                if (del > 100 && del < 120)
 
422
                        shot->shotAniMax = (del - 100 + 1);
 
423
                else
 
424
                        shot->shotAniMax = weapon->weapani + 1;
 
425
 
 
426
                if (del == 99 || del == 98)
 
427
                {
 
428
                        tmp_by = PX - mouseX;
 
429
                        if (tmp_by < -5)
 
430
                                tmp_by = -5;
 
431
                        else if (tmp_by > 5)
 
432
                                tmp_by = 5;
 
433
                        shot->shotXM += tmp_by;
 
434
                }
 
435
 
 
436
                if (del == 99 || del == 100)
 
437
                {
 
438
                        tmp_by = PY - mouseY - weapon->sy[shotMultiPos[bay_i]-1];
 
439
                        if (tmp_by < -4)
 
440
                                tmp_by = -4;
 
441
                        else if (tmp_by > 4)
 
442
                                tmp_by = 4;
 
443
                        shot->shotYM = tmp_by;
 
444
                }
 
445
                else if (weapon->sy[shotMultiPos[bay_i]-1] == 98)
 
446
                {
 
447
                        shot->shotYM = 0;
 
448
                        shot->shotYC = -1;
 
449
                }
 
450
                else if (weapon->sy[shotMultiPos[bay_i]-1] > 100)
 
451
                {
 
452
                        shot->shotYM = weapon->sy[shotMultiPos[bay_i]-1];
 
453
                        shot->shotY -= player[shot->playerNumber-1].delta_y_shot_move;
 
454
                }
 
455
                else
 
456
                {
 
457
                        shot->shotYM = -weapon->sy[shotMultiPos[bay_i]-1];
 
458
                }
 
459
 
 
460
                if (weapon->sx[shotMultiPos[bay_i]-1] > 100)
 
461
                {
 
462
                        shot->shotXM = weapon->sx[shotMultiPos[bay_i]-1];
 
463
                        shot->shotX -= player[shot->playerNumber-1].delta_x_shot_move;
 
464
                        if (shot->shotXM == 101)
 
465
                                shot->shotY -= player[shot->playerNumber-1].delta_y_shot_move;
 
466
                }
 
467
 
 
468
 
 
469
                if (weapon->aim > 5)  /*Guided Shot*/
 
470
                {
 
471
                        uint best_dist = 65000;
 
472
                        JE_byte closest_enemy = 0;
 
473
                        /*Find Closest Enemy*/
 
474
                        for (x = 0; x < 100; x++)
 
475
                        {
 
476
                                if (enemyAvail[x] != 1 && !enemy[x].scoreitem)
 
477
                                {
 
478
                                        y = abs(enemy[x].ex - shot->shotX) + abs(enemy[x].ey - shot->shotY);
 
479
                                        if (y < best_dist)
 
480
                                        {
 
481
                                                best_dist = y;
 
482
                                                closest_enemy = x + 1;
 
483
                                        }
 
484
                                }
 
485
                        }
 
486
                        shot->aimAtEnemy = closest_enemy;
 
487
                        shot->aimDelay = 5;
 
488
                        shot->aimDelayMax = weapon->aim - 5;
 
489
                }
 
490
                else
 
491
                {
 
492
                        shot->aimAtEnemy = 0;
 
493
                }
 
494
 
 
495
                shotRepeat[bay_i] = weapon->shotrepeat;
 
496
        }
 
497
 
 
498
        return shot_id;
 
499
}