2019-09-19 22:42:45 +00:00
//-------------------------------------------------------------------------
/*
Copyright ( C ) 2010 - 2019 EDuke32 developers and contributors
Copyright ( C ) 2019 Nuke . YKT
This file is part of NBlood .
NBlood is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*/
//-------------------------------------------------------------------------
2019-09-21 18:59:54 +00:00
//#include <iostream>
# include "ns.h" // Must come before everything else!
2019-09-19 22:42:45 +00:00
# include "build.h"
2020-09-06 10:44:58 +00:00
# include "automap.h"
2020-11-21 20:31:50 +00:00
# include "savegamehelp.h"
2019-09-19 22:42:45 +00:00
# include "blood.h"
2019-09-22 06:39:22 +00:00
BEGIN_BLD_NS
2020-02-11 22:15:25 +00:00
VECTORDATA gVectorData [ ] = { // this is constant EXCEPT for [VECTOR_TYPE_20].maxDist. What were they thinking...
2020-12-02 19:05:53 +00:00
// Tine
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
17 ,
174762 ,
1152 ,
10240 ,
0 ,
1 ,
20480 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_43 , FX_5 , FX_NONE , 500 ,
FX_NONE , FX_5 , FX_NONE , 501 ,
FX_43 , FX_6 , FX_NONE , 502 ,
FX_43 , FX_0 , FX_NONE , 503 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_7 , 502 ,
FX_43 , FX_6 , FX_7 , 502 ,
FX_NONE , FX_NONE , FX_NONE , 503 ,
FX_43 , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 503 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , - 1 ,
} ,
2020-01-26 11:19:01 +00:00
2020-12-02 19:05:53 +00:00
// Shell
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
4 ,
65536 ,
0 ,
8192 ,
0 ,
1 ,
12288 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_43 , FX_5 , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , 501 ,
FX_43 , FX_6 , FX_NONE , - 1 ,
FX_43 , FX_0 , FX_NONE , - 1 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_43 , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_43 , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , - 1 ,
} ,
// Bullet
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
7 ,
21845 ,
0 ,
32768 ,
0 ,
1 ,
12288 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_43 , FX_5 , FX_7 , 510 ,
FX_NONE , FX_5 , FX_7 , 511 ,
FX_43 , FX_6 , FX_NONE , 512 ,
FX_43 , FX_0 , FX_NONE , 513 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_7 , 512 ,
FX_43 , FX_6 , FX_7 , 512 ,
FX_NONE , FX_NONE , FX_NONE , 513 ,
FX_43 , FX_NONE , FX_NONE , 513 ,
FX_NONE , FX_6 , FX_NONE , 513 ,
FX_NONE , FX_6 , FX_NONE , 513 ,
FX_NONE , FX_6 , FX_NONE , 513 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , - 1 ,
2020-01-26 11:19:01 +00:00
2020-12-02 19:05:53 +00:00
} ,
// Tommy AP
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
20 ,
65536 ,
0 ,
16384 ,
0 ,
1 ,
20480 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_43 , FX_5 , FX_7 , 510 ,
FX_NONE , FX_5 , FX_7 , 511 ,
FX_43 , FX_6 , FX_NONE , 512 ,
FX_43 , FX_0 , FX_NONE , 513 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_7 , 512 ,
FX_43 , FX_6 , FX_7 , 512 ,
FX_NONE , FX_NONE , FX_NONE , 513 ,
FX_43 , FX_NONE , FX_NONE , 513 ,
FX_NONE , FX_6 , FX_NONE , 513 ,
FX_NONE , FX_6 , FX_NONE , 513 ,
FX_NONE , FX_6 , FX_NONE , 513 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , - 1 ,
} ,
// Shell AP
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
6 ,
87381 ,
0 ,
12288 ,
0 ,
1 ,
6144 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_43 , FX_5 , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , 501 ,
FX_43 , FX_6 , FX_NONE , - 1 ,
FX_43 , FX_0 , FX_NONE , - 1 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_43 , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_43 , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , - 1 ,
} ,
// Tommy regular
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
12 ,
65536 ,
0 ,
16384 ,
0 ,
1 ,
12288 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_43 , FX_5 , FX_7 , 510 ,
FX_NONE , FX_5 , FX_7 , 511 ,
FX_43 , FX_6 , FX_NONE , 512 ,
FX_43 , FX_0 , FX_NONE , 513 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_7 , 512 ,
FX_43 , FX_6 , FX_7 , 512 ,
FX_NONE , FX_NONE , FX_NONE , 513 ,
FX_43 , FX_NONE , FX_NONE , 513 ,
FX_NONE , FX_6 , FX_NONE , 513 ,
FX_NONE , FX_6 , FX_NONE , 513 ,
FX_NONE , FX_6 , FX_NONE , 513 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , - 1 ,
} ,
// Bat bite
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
4 ,
0 ,
921 ,
0 ,
0 ,
1 ,
4096 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_0 , FX_NONE , 503 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
} ,
// Eel bite
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
12 ,
0 ,
1177 ,
0 ,
0 ,
0 ,
0 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , 500 ,
FX_NONE , FX_5 , FX_NONE , 501 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_0 , FX_NONE , 503 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
} ,
// Gill bite
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
9 ,
0 ,
1177 ,
0 ,
0 ,
0 ,
0 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , 500 ,
FX_NONE , FX_5 , FX_NONE , 501 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_0 , FX_NONE , 503 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
} ,
// Beast slash
{
2021-06-16 19:13:04 +00:00
kDamageExplode ,
2020-12-02 19:05:53 +00:00
50 ,
43690 ,
1024 ,
8192 ,
0 ,
4 ,
32768 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , 500 ,
FX_NONE , FX_5 , FX_NONE , 501 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_0 , FX_NONE , 503 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
} ,
// Axe
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
18 ,
436906 ,
1024 ,
16384 ,
0 ,
2 ,
20480 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , 500 ,
FX_NONE , FX_5 , FX_NONE , 501 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_0 , FX_NONE , 503 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , - 1 ,
} ,
// Cleaver
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
9 ,
218453 ,
1024 ,
0 ,
0 ,
1 ,
24576 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , 500 ,
FX_NONE , FX_5 , FX_NONE , 501 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_0 , FX_NONE , 503 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , - 1 ,
} ,
// Phantasm slash
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
20 ,
436906 ,
1024 ,
16384 ,
0 ,
3 ,
24576 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , 500 ,
FX_NONE , FX_5 , FX_NONE , 501 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_0 , FX_NONE , 503 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , - 1 ,
} ,
2020-01-26 11:19:01 +00:00
2020-12-02 19:05:53 +00:00
// Gargoyle Slash
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
16 ,
218453 ,
1024 ,
8192 ,
0 ,
4 ,
20480 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , 500 ,
FX_NONE , FX_5 , FX_NONE , 501 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_0 , FX_NONE , 503 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , - 1 ,
} ,
2020-01-26 11:19:01 +00:00
2020-12-02 19:05:53 +00:00
// Cerberus bite
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
19 ,
218453 ,
614 ,
8192 ,
0 ,
2 ,
24576 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , 500 ,
FX_NONE , FX_5 , FX_NONE , 501 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_0 , FX_NONE , 503 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
} ,
2020-01-26 11:19:01 +00:00
2020-12-02 19:05:53 +00:00
// Hound bite
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
10 ,
218453 ,
614 ,
8192 ,
0 ,
2 ,
24576 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , 500 ,
FX_NONE , FX_5 , FX_NONE , 501 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_0 , FX_NONE , 503 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
} ,
2020-01-26 11:19:01 +00:00
2020-12-02 19:05:53 +00:00
// Rat bite
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
4 ,
0 ,
921 ,
0 ,
0 ,
1 ,
24576 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_0 , FX_NONE , 503 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
} ,
2020-01-26 11:19:01 +00:00
2020-12-02 19:05:53 +00:00
// Spider bite
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
8 ,
0 ,
614 ,
0 ,
0 ,
1 ,
24576 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , 500 ,
FX_NONE , FX_5 , FX_NONE , 501 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_0 , FX_NONE , 503 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
} ,
2020-01-26 11:19:01 +00:00
2020-12-02 19:05:53 +00:00
// Unk
{
2021-06-16 19:13:04 +00:00
kDamageBullet ,
2020-12-02 19:05:53 +00:00
9 ,
0 ,
512 ,
0 ,
0 ,
0 ,
0 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_5 , FX_NONE , 500 ,
FX_NONE , FX_5 , FX_NONE , 501 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_0 , FX_NONE , 503 ,
FX_NONE , FX_4 , FX_NONE , - 1 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_6 , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , 502 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
} ,
{
( DAMAGE_TYPE ) - 1 ,
0 ,
0 ,
2560 ,
0 ,
0 ,
0 ,
0 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_34 , FX_35 , - 1 ,
FX_NONE , FX_34 , FX_35 , - 1 ,
FX_NONE , FX_34 , FX_35 , - 1 ,
FX_NONE , FX_34 , FX_35 , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_34 , FX_35 , - 1 ,
FX_NONE , FX_34 , FX_35 , - 1 ,
FX_NONE , FX_34 , FX_35 , - 1 ,
FX_NONE , FX_34 , FX_35 , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
} ,
2020-01-26 11:19:01 +00:00
2020-12-02 19:05:53 +00:00
// Tchernobog burn vector
{
2021-06-16 19:13:04 +00:00
kDamageBurn ,
2020-12-02 19:05:53 +00:00
2 ,
0 ,
0 ,
0 ,
15 ,
0 ,
0 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
} ,
2020-01-26 11:19:01 +00:00
2020-12-02 19:05:53 +00:00
// Vodoo 1.0 vector
{
2021-06-16 19:13:04 +00:00
kDamageSpirit ,
2020-12-02 19:05:53 +00:00
25 ,
0 ,
0 ,
0 ,
0 ,
0 ,
0 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
} ,
2020-01-26 11:19:01 +00:00
2020-12-02 19:05:53 +00:00
// 22 kVectorGenDudePunch
{
2021-06-16 19:13:04 +00:00
kDamageFall ,
2020-12-02 19:05:53 +00:00
37 ,
874762 ,
620 ,
0 ,
0 ,
0 ,
0 ,
FX_NONE , FX_NONE , FX_NONE , - 1 ,
FX_NONE , FX_NONE , FX_NONE , 357 ,
FX_NONE , FX_NONE , FX_NONE , 357 ,
FX_NONE , FX_NONE , FX_NONE , 357 ,
FX_NONE , FX_NONE , FX_NONE , 357 ,
FX_NONE , FX_NONE , FX_NONE , 357 ,
FX_NONE , FX_NONE , FX_NONE , 357 ,
FX_NONE , FX_NONE , FX_NONE , 357 ,
FX_NONE , FX_NONE , FX_NONE , 357 ,
FX_NONE , FX_NONE , FX_NONE , 357 ,
FX_NONE , FX_NONE , FX_NONE , 357 ,
FX_NONE , FX_NONE , FX_NONE , 357 ,
FX_NONE , FX_NONE , FX_NONE , 357 ,
FX_NONE , FX_NONE , FX_NONE , 357 ,
FX_NONE , FX_NONE , FX_NONE , 357 ,
} ,
2019-09-19 22:42:45 +00:00
} ;
2020-02-11 22:15:25 +00:00
const ITEMDATA gItemData [ ] = {
2020-12-02 19:05:53 +00:00
{
0 ,
2552 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
- 1 ,
} ,
{
0 ,
2553 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
- 1 ,
} ,
{
0 ,
2554 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
- 1 ,
} ,
{
0 ,
2555 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
- 1 ,
} ,
{
0 ,
2556 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
- 1 ,
} ,
{
0 ,
2557 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
- 1 ,
} ,
{
0 ,
2021-04-17 10:05:37 +00:00
2558 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
2021-04-17 10:05:37 +00:00
32 ,
32 ,
2020-12-02 19:05:53 +00:00
- 1 ,
} ,
{
0 ,
519 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
0 ,
} ,
{
0 ,
822 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
2169 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
2433 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
517 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
783 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
896 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
825 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
827 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
4 ,
} ,
{
0 ,
828 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
829 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
830 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
80 ,
64 ,
1 ,
} ,
{
0 ,
831 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
863 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
760 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
2 ,
} ,
{
0 ,
836 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
851 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
2428 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
839 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
3 ,
} ,
{
0 ,
768 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
64 ,
64 ,
- 1 ,
} ,
{
0 ,
840 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
- 1 ,
} ,
{
0 ,
841 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
- 1 ,
} ,
{
0 ,
842 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
- 1 ,
} ,
{
0 ,
843 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
- 1 ,
} ,
{
0 ,
683 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
521 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
604 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
520 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
803 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
518 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
522 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
523 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
- 1 ,
} ,
{
0 ,
837 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
80 ,
64 ,
- 1 ,
} ,
{
0 ,
2628 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
64 ,
64 ,
- 1 ,
} ,
{
0 ,
2586 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
64 ,
64 ,
- 1 ,
} ,
{
0 ,
2578 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
64 ,
64 ,
- 1 ,
} ,
{
0 ,
2602 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
64 ,
64 ,
- 1 ,
} ,
{
0 ,
2594 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
64 ,
64 ,
- 1 ,
} ,
{
0 ,
753 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
64 ,
64 ,
- 1 ,
} ,
{
0 ,
753 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
7 ,
64 ,
64 ,
- 1 ,
} ,
{
0 ,
3558 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
0 ,
64 ,
64 ,
- 1 ,
} ,
{
0 ,
3558 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
7 ,
64 ,
64 ,
- 1 ,
}
2019-09-19 22:42:45 +00:00
} ;
2020-02-11 22:15:25 +00:00
const AMMOITEMDATA gAmmoItemData [ ] = {
2020-12-02 19:05:53 +00:00
{
0 ,
618 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
480 ,
6 ,
7
} ,
{
0 ,
589 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
1 ,
5 ,
6
} ,
{
0 ,
589 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
1 ,
5 ,
6
} ,
{
0 ,
809 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
5 ,
5 ,
6
} ,
{
0 ,
811 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
1 ,
10 ,
11
} ,
{
0 ,
810 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
1 ,
11 ,
12
} ,
{
0 ,
820 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
24 ,
24 ,
10 ,
8 ,
0
} ,
{
0 ,
619 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
4 ,
2 ,
0
} ,
{
0 ,
812 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
15 ,
2 ,
0
} ,
{
0 ,
813 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
15 ,
3 ,
0
} ,
{
0 ,
525 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
100 ,
9 ,
10
} ,
{
0 ,
814 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
15 ,
255 ,
0
} ,
{
0 ,
817 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
100 ,
3 ,
0
} ,
{
0 ,
548 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
24 ,
24 ,
32 ,
7 ,
0
} ,
{
0 ,
0 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
6 ,
255 ,
0
} ,
{
0 ,
0 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
6 ,
255 ,
0
} ,
{
0 ,
816 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
8 ,
1 ,
0
} ,
{
0 ,
818 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
8 ,
255 ,
0
} ,
{
0 ,
819 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
8 ,
255 ,
0
} ,
{
0 ,
801 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
6 ,
4 ,
0
} ,
{
0 ,
0 ,
0 ,
0 ,
0 ,
0 ,
0 ,
0 ,
0
} ,
2019-09-19 22:42:45 +00:00
} ;
2020-02-11 22:15:25 +00:00
const WEAPONITEMDATA gWeaponItemData [ ] = {
2020-12-02 19:05:53 +00:00
{
0 ,
- 1 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
0 ,
- 1 ,
0
} ,
{
0 ,
559 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
3 ,
2 ,
8
} ,
{
0 ,
558 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
4 ,
3 ,
50
} ,
{
0 ,
524 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
2 ,
1 ,
9
} ,
{
0 ,
525 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
10 ,
9 ,
100
} ,
{
0 ,
539 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
8 ,
7 ,
64
} ,
{
0 ,
526 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
5 ,
4 ,
6
} ,
{
0 ,
- 1 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
1 ,
- 1 ,
0
} ,
{
0 ,
618 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
7 ,
6 ,
480
} ,
{
0 ,
589 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
6 ,
5 ,
1
} ,
{
0 ,
800 ,
2021-04-17 08:22:00 +00:00
- 8 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
9 ,
8 ,
35
}
2019-09-19 22:42:45 +00:00
} ;
2020-02-11 22:15:25 +00:00
const MissileType missileInfo [ ] = {
2020-12-02 19:05:53 +00:00
// Cleaver
{
2138 ,
978670 ,
512 ,
40 ,
40 ,
2021-04-17 08:22:00 +00:00
- 16 ,
2020-12-02 19:05:53 +00:00
16 ,
} ,
// Regular flare
{
2424 ,
3145728 ,
0 ,
32 ,
32 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
32 ,
} ,
// Tesla alt
{
3056 ,
2796202 ,
0 ,
32 ,
32 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
32 ,
} ,
// Flare alt
{
2424 ,
2446677 ,
0 ,
32 ,
32 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
4 ,
} ,
// Spray flame
{
0 ,
1118481 ,
0 ,
24 ,
24 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
16 ,
} ,
// Fireball
{
0 ,
1118481 ,
0 ,
32 ,
32 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
32 ,
} ,
// Tesla regular
{
2130 ,
2796202 ,
0 ,
32 ,
32 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
16 ,
} ,
// EctoSkull
{
870 ,
699050 ,
0 ,
32 ,
32 ,
2021-04-17 08:22:00 +00:00
- 24 ,
2020-12-02 19:05:53 +00:00
32 ,
} ,
// Hellhound flame
{
0 ,
1118481 ,
0 ,
24 ,
24 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
16 ,
} ,
// Puke
{
0 ,
838860 ,
0 ,
16 ,
16 ,
2021-04-17 08:22:00 +00:00
- 16 ,
2020-12-02 19:05:53 +00:00
16 ,
} ,
// Reserved
{
0 ,
838860 ,
0 ,
8 ,
8 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
16 ,
} ,
// Stone gargoyle projectile
{
3056 ,
2097152 ,
0 ,
32 ,
32 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
16 ,
} ,
// Napalm launcher
{
0 ,
2446677 ,
0 ,
30 ,
30 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
24 ,
} ,
// Cerberus fireball
{
0 ,
2446677 ,
0 ,
30 ,
30 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
24 ,
} ,
// Tchernobog fireball
{
0 ,
1398101 ,
0 ,
24 ,
24 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
16 ,
} ,
// Regular life leech
{
2446 ,
2796202 ,
0 ,
32 ,
32 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
16 ,
} ,
// Dropped life leech (enough ammo)
{
3056 ,
2446677 ,
0 ,
16 ,
16 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
16 ,
} ,
// Dropped life leech (no ammo)
{
3056 ,
1747626 ,
0 ,
32 ,
32 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
16 ,
}
2019-09-19 22:42:45 +00:00
} ;
2019-12-06 23:07:02 +00:00
const THINGINFO thingInfo [ ] = {
2020-12-02 19:05:53 +00:00
//TNT Barrel
{
25 ,
250 ,
32 ,
11 ,
4096 ,
80 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_YCENTER | CSTAT_SPRITE_BLOCK_HITSCAN ,
2020-12-02 19:05:53 +00:00
907 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
256 , 256 , 128 , 64 , 0 , 0 , 128 ,
} ,
2021-09-16 19:59:39 +00:00
2020-12-02 19:05:53 +00:00
// Armed Proxy Dynamite
{
5 ,
5 ,
16 ,
3 ,
24576 ,
1600 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_HITSCAN ,
2020-12-02 19:05:53 +00:00
3444 ,
2021-04-17 08:22:00 +00:00
- 16 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
256 , 256 , 256 , 64 , 0 , 0 , 512 ,
} ,
// Armed Remote Dynamite
{
5 ,
5 ,
16 ,
3 ,
24576 ,
1600 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_HITSCAN ,
2020-12-02 19:05:53 +00:00
3457 ,
2021-04-17 08:22:00 +00:00
- 16 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
256 , 256 , 256 , 64 , 0 , 0 , 512 ,
} ,
// Vase1
{
1 ,
20 ,
32 ,
3 ,
32768 ,
80 ,
0 ,
739 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
256 , 0 , 256 , 128 , 0 , 0 , 0 ,
} ,
// Vase2
{
1 ,
150 ,
32 ,
3 ,
32768 ,
80 ,
0 ,
642 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
256 , 256 , 256 , 128 , 0 , 0 , 0 ,
} ,
// Crate face
{
10 ,
0 ,
0 ,
0 ,
0 ,
0 ,
0 ,
462 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
0 , 0 , 0 , 256 , 0 , 0 , 0 ,
} ,
// Glass window
{
1 ,
0 ,
0 ,
0 ,
0 ,
0 ,
0 ,
266 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
256 , 0 , 256 , 256 , 0 , 0 , 0 ,
} ,
// Flourescent Light
{
1 ,
0 ,
0 ,
0 ,
0 ,
0 ,
0 ,
796 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
256 , 0 , 256 , 256 , 0 , 0 , 512 ,
} ,
// Wall Crack
{
50 ,
0 ,
0 ,
0 ,
0 ,
0 ,
0 ,
1127 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
0 , 0 , 0 , 256 , 0 , 0 , 0 ,
} ,
// Wood Beam
{
8 ,
0 ,
0 ,
0 ,
0 ,
0 ,
0 ,
1142 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
256 , 0 , 256 , 128 , 0 , 0 , 0 ,
} ,
// Spider's Web
{
4 ,
0 ,
0 ,
0 ,
0 ,
0 ,
0 ,
1069 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
256 , 256 , 64 , 256 , 0 , 0 , 128 ,
} ,
// Metal Grate
{
40 ,
0 ,
0 ,
0 ,
0 ,
0 ,
0 ,
483 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
64 , 0 , 128 , 256 , 0 , 0 , 0 ,
} ,
// Flammable Tree
{
1 ,
0 ,
0 ,
0 ,
0 ,
0 ,
0 ,
- 1 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
0 , 256 , 0 , 256 , 0 , 0 , 128 ,
} ,
// MachineGun Trap
{
1000 ,
0 ,
0 ,
8 ,
0 ,
0 ,
0 ,
- 1 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
0 , 0 , 128 , 256 , 0 , 0 , 512 ,
} ,
// Falling Rock
{
0 ,
15 ,
8 ,
3 ,
32768 ,
0 ,
0 ,
- 1 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 ,
} ,
// Kickable Pail
{
0 ,
8 ,
48 ,
3 ,
49152 ,
0 ,
0 ,
- 1 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 ,
} ,
// Gib Object
{
10 ,
2 ,
0 ,
0 ,
32768 ,
0 ,
0 ,
- 1 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
256 , 0 , 256 , 256 , 0 , 0 , 128 ,
} ,
// Explode Object
{
20 ,
2 ,
0 ,
0 ,
32768 ,
0 ,
0 ,
- 1 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
0 , 0 , 0 , 256 , 0 , 0 , 128 ,
} ,
// Armed stick Of TNT
{
5 ,
14 ,
16 ,
3 ,
24576 ,
1600 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_HITSCAN ,
2020-12-02 19:05:53 +00:00
3422 ,
2021-04-17 08:22:00 +00:00
- 32 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
64 , 256 , 128 , 64 , 0 , 0 , 256 ,
} ,
// Armed bundle Of TNT
{
5 ,
14 ,
16 ,
3 ,
24576 ,
1600 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_HITSCAN ,
2020-12-02 19:05:53 +00:00
3433 ,
2021-04-17 08:22:00 +00:00
- 32 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
64 , 256 , 128 , 64 , 0 , 0 , 256 ,
} ,
// Armed aerosol
{
5 ,
14 ,
16 ,
3 ,
32768 ,
1600 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_HITSCAN ,
2020-12-02 19:05:53 +00:00
3467 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
64 , 256 , 128 , 64 , 0 , 0 , 256 ,
} ,
// Bone (Flesh Garg.)
{
5 ,
6 ,
16 ,
3 ,
32768 ,
1600 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_HITSCAN ,
2020-12-02 19:05:53 +00:00
1462 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 ,
} ,
// Some alpha stuff
{
8 ,
3 ,
16 ,
11 ,
32768 ,
1600 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_HITSCAN ,
2020-12-02 19:05:53 +00:00
- 1 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
256 , 0 , 256 , 256 , 0 , 0 , 0 ,
} ,
// WaterDrip
{
0 ,
1 ,
1 ,
2 ,
0 ,
0 ,
0 ,
1147 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
10 ,
0 ,
0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 ,
} ,
// BloodDrip
{
0 ,
1 ,
1 ,
2 ,
0 ,
0 ,
0 ,
1160 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
2 ,
0 ,
0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 ,
} ,
// Blood chucks1
{
15 ,
4 ,
4 ,
3 ,
24576 ,
0 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_ALL ,
2020-12-02 19:05:53 +00:00
- 1 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
128 , 64 , 256 , 256 , 0 , 0 , 256 ,
} ,
// Blood chucks2
{
30 ,
30 ,
8 ,
3 ,
8192 ,
0 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_ALL ,
2020-12-02 19:05:53 +00:00
- 1 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
0 ,
0 ,
128 , 64 , 256 , 256 , 0 , 0 , 64 ,
} ,
// Axe Zombie Head
{
60 ,
5 ,
32 ,
3 ,
40960 ,
1280 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_ALL ,
2020-12-02 19:05:53 +00:00
3405 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
40 ,
40 ,
128 , 64 , 256 , 256 , 0 , 0 , 64 ,
} ,
// Napalm's Alt Fire explosion
{
80 ,
30 ,
32 ,
3 ,
57344 ,
1600 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_HITSCAN ,
2020-12-02 19:05:53 +00:00
3281 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 ,
} ,
// Fire Pod Explosion
{
80 ,
30 ,
32 ,
3 ,
57344 ,
1600 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_HITSCAN ,
2020-12-02 19:05:53 +00:00
2020 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
256 , 0 , 256 , 256 , 0 , 0 , 0 ,
} ,
// Green Pod Explosion
{
80 ,
30 ,
32 ,
3 ,
57344 ,
1600 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_HITSCAN ,
2020-12-02 19:05:53 +00:00
1860 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
256 , 0 , 256 , 256 , 0 , 0 , 0 ,
} ,
// Life Leech
{
150 ,
30 ,
48 ,
3 ,
32768 ,
1600 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_ALL ,
2020-12-02 19:05:53 +00:00
800 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
0 ,
48 ,
48 ,
64 , 64 , 112 , 64 , 0 , 96 , 96 ,
} ,
// Voodoo Head
{
1 ,
30 ,
48 ,
3 ,
32768 ,
1600 ,
0 ,
2443 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
0 ,
16 ,
16 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 ,
} ,
// 433 - kModernThingTNTProx
{
5 ,
5 ,
16 ,
3 ,
24576 ,
1600 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_HITSCAN ,
2020-12-02 19:05:53 +00:00
3444 ,
2021-04-17 08:22:00 +00:00
- 16 ,
2020-12-02 19:05:53 +00:00
7 ,
32 ,
32 ,
256 , 256 , 256 , 64 , 0 , 0 , 512 ,
} ,
// 434 - kModernThingThrowableRock
{
5 ,
6 ,
16 ,
3 ,
32768 ,
1600 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_HITSCAN ,
2020-12-02 19:05:53 +00:00
1462 ,
2021-04-17 08:22:00 +00:00
0 ,
2020-12-02 19:05:53 +00:00
0 ,
32 ,
32 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 ,
} ,
// 435 - kModernThingEnemyLifeLeech
{
150 ,
30 ,
48 ,
3 ,
32768 ,
1600 ,
2021-12-18 18:19:28 +00:00
CSTAT_SPRITE_BLOCK_ALL ,
2020-12-02 19:05:53 +00:00
800 ,
2021-04-17 08:22:00 +00:00
- 128 ,
2020-12-02 19:05:53 +00:00
0 ,
44 ,
44 ,
0 , 1024 , 512 , 1024 , 0 , 64 , 512 ,
} ,
2019-09-19 22:42:45 +00:00
} ;
2020-02-11 22:15:25 +00:00
const EXPLOSION explodeInfo [ ] = {
2020-12-02 19:05:53 +00:00
{
40 ,
10 ,
10 ,
75 ,
450 ,
0 ,
60 ,
80 ,
40
} ,
{
80 ,
20 ,
10 ,
150 ,
900 ,
0 ,
60 ,
160 ,
60
} ,
{
120 ,
40 ,
15 ,
225 ,
1350 ,
0 ,
60 ,
240 ,
80
} ,
{
80 ,
5 ,
10 ,
120 ,
20 ,
10 ,
60 ,
0 ,
40
} ,
{
120 ,
10 ,
10 ,
180 ,
40 ,
10 ,
60 ,
0 ,
80
} ,
{
160 ,
15 ,
10 ,
240 ,
60 ,
10 ,
60 ,
0 ,
120
} ,
{
40 ,
20 ,
10 ,
120 ,
0 ,
10 ,
30 ,
60 ,
40
} ,
{
80 ,
20 ,
10 ,
150 ,
800 ,
5 ,
60 ,
160 ,
60
} ,
2019-09-19 22:42:45 +00:00
} ;
2021-11-19 19:50:02 +00:00
static const int16_t gPlayerGibThingComments [ ] = {
2020-12-02 19:05:53 +00:00
734 , 735 , 736 , 737 , 738 , 739 , 740 , 741 , 3038 , 3049
2019-09-19 22:42:45 +00:00
} ;
2021-11-19 19:50:02 +00:00
const int16_t DudeDifficulty [ 5 ] = {
2020-12-02 19:22:13 +00:00
512 , 384 , 256 , 208 , 160
} ;
2019-09-19 22:42:45 +00:00
2021-09-16 19:59:39 +00:00
struct POSTPONE
2021-08-30 18:12:19 +00:00
{
DBloodActor * sprite ;
int status ;
2019-09-19 22:42:45 +00:00
} ;
2021-08-30 18:12:19 +00:00
TArray < POSTPONE > gPost ;
2019-09-19 22:42:45 +00:00
2020-12-02 19:22:13 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-11-19 17:08:05 +00:00
bool IsUnderwaterSector ( sectortype * pSector )
2019-09-19 22:42:45 +00:00
{
2021-11-19 17:08:05 +00:00
return ! ! pSector - > hasX ( ) & & pSector - > xs ( ) . Underwater ;
2019-09-19 22:42:45 +00:00
}
2020-12-02 19:22:13 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-09-19 22:42:45 +00:00
2020-12-02 19:55:08 +00:00
static void actInitTraps ( )
2020-12-02 16:10:00 +00:00
{
2020-12-02 19:22:13 +00:00
BloodStatIterator it ( kStatTraps ) ;
while ( auto act = it . Next ( ) )
{
spritetype * pSprite = & act - > s ( ) ;
if ( pSprite - > type = = kTrapExploder )
{
2021-12-18 18:19:28 +00:00
pSprite - > cstat & = ~ CSTAT_SPRITE_BLOCK ;
2020-12-02 19:22:13 +00:00
pSprite - > cstat | = CSTAT_SPRITE_INVISIBLE ;
if ( ! act - > hasX ( ) ) continue ;
auto x = & act - > x ( ) ;
x - > waitTime = ClipLow ( x - > waitTime , 1 ) ;
x - > state = 0 ;
}
}
}
2019-10-12 20:45:46 +00:00
2020-12-02 19:22:13 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-10-12 20:45:46 +00:00
2020-12-02 19:55:08 +00:00
static void actInitThings ( )
2020-12-02 19:22:13 +00:00
{
BloodStatIterator it ( kStatThing ) ;
while ( auto act = it . Next ( ) )
{
if ( ! act - > hasX ( ) ) continue ;
spritetype * pSprite = & act - > s ( ) ;
XSPRITE * pXSprite = & act - > x ( ) ;
2019-09-21 11:02:17 +00:00
2020-12-02 19:22:13 +00:00
int nType = pSprite - > type - kThingBase ;
pXSprite - > health = thingInfo [ nType ] . startHealth < < 4 ;
# ifdef NOONE_EXTENSIONS
// allow level designer to set custom clipdist.
// this is especially useful for various Gib and Explode objects which have clipdist 1 for some reason predefined,
// but what if it have voxel model...?
if ( ! gModernMap )
# endif
pSprite - > clipdist = thingInfo [ nType ] . clipdist ;
2019-09-21 11:02:17 +00:00
2020-12-02 19:22:13 +00:00
pSprite - > flags = thingInfo [ nType ] . flags ;
if ( pSprite - > flags & kPhysGravity ) pSprite - > flags | = kPhysFalling ;
2021-09-04 10:52:02 +00:00
act - > xvel = act - > yvel = act - > zvel = 0 ;
2020-12-02 16:10:00 +00:00
2021-09-16 19:59:39 +00:00
switch ( pSprite - > type )
2021-09-15 22:52:54 +00:00
{
2020-12-02 19:22:13 +00:00
case kThingArmedProxBomb :
case kTrapMachinegun :
# ifdef NOONE_EXTENSIONS
case kModernThingTNTProx :
# endif
pXSprite - > state = 0 ;
break ;
2021-08-25 06:46:31 +00:00
case kThingBloodChunks :
2020-12-03 19:30:30 +00:00
{
2021-09-05 07:59:10 +00:00
SEQINST * pInst = GetInstance ( act ) ;
2020-12-02 19:22:13 +00:00
if ( pInst )
{
auto seq = getSequence ( pInst - > nSeqID ) ;
if ( ! seq ) break ;
2020-12-03 19:30:30 +00:00
seqSpawn ( pInst - > nSeqID , act ) ;
2020-12-02 19:22:13 +00:00
}
break ;
}
default :
pXSprite - > state = 1 ;
break ;
}
}
}
2019-09-19 22:42:45 +00:00
2020-12-02 19:22:13 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-12-02 16:10:00 +00:00
2020-12-02 19:55:08 +00:00
static void actInitDudes ( )
2020-12-02 19:22:13 +00:00
{
if ( gGameOptions . nMonsterSettings = = 0 )
{
gKillMgr . SetCount ( 0 ) ;
BloodStatIterator it ( kStatDude ) ;
while ( auto act = it . Next ( ) )
{
if ( act - > hasX ( ) & & act - > x ( ) . key > 0 ) // Drop Key
2020-12-02 23:20:14 +00:00
actDropObject ( act , kItemKeyBase + ( act - > x ( ) . key - 1 ) ) ;
2020-12-02 19:22:13 +00:00
DeleteSprite ( act ) ;
}
}
else
{
// by NoOne: WTF is this?
///////////////
BloodStatIterator it ( kStatDude ) ;
while ( auto act = it . Next ( ) )
{
spritetype * pSprite = & act - > s ( ) ;
if ( pSprite - > type < kDudeBase | | pSprite - > type > = kDudeMax )
2021-09-06 20:47:10 +00:00
I_Error ( " Non-enemy sprite (%d) in the enemy sprite list. \n " , act - > GetIndex ( ) ) ;
2020-12-02 19:22:13 +00:00
}
2019-09-21 11:02:17 +00:00
2020-12-02 19:22:13 +00:00
gKillMgr . CountTotalKills ( ) ;
///////////////
for ( int i = 0 ; i < kDudeMax - kDudeBase ; i + + )
for ( int j = 0 ; j < 7 ; j + + )
2020-12-02 23:30:19 +00:00
dudeInfo [ i ] . damageVal [ j ] = MulScale ( DudeDifficulty [ gGameOptions . nDifficulty ] , dudeInfo [ i ] . startDamage [ j ] , 8 ) ;
2020-12-02 19:22:13 +00:00
it . Reset ( kStatDude ) ;
while ( auto act = it . Next ( ) )
{
if ( ! act - > hasX ( ) ) continue ;
spritetype * pSprite = & act - > s ( ) ;
XSPRITE * pXSprite = & act - > x ( ) ;
int nType = pSprite - > type - kDudeBase ;
int seqStartId = dudeInfo [ nType ] . seqStartID ;
if ( ! act - > IsPlayerActor ( ) )
{
# ifdef NOONE_EXTENSIONS
switch ( pSprite - > type )
{
case kDudeModernCustom :
case kDudeModernCustomBurning :
2021-12-18 18:34:18 +00:00
pSprite - > cstat | = CSTAT_SPRITE_BLOOD_BIT1 | CSTAT_SPRITE_BLOCK_ALL ;
2021-05-06 08:51:39 +00:00
seqStartId = genDudeSeqStartId ( act ) ; // Custom Dude stores its SEQ in data2
2020-12-02 19:22:13 +00:00
pXSprite - > sysData1 = pXSprite - > data3 ; // move sndStartId to sysData1, because data3 used by the game;
pXSprite - > data3 = 0 ;
break ;
case kDudePodMother : // FakeDude type (no seq, custom flags, clipdist and cstat)
if ( gModernMap ) break ;
[[fallthrough]] ;
default :
pSprite - > clipdist = dudeInfo [ nType ] . clipdist ;
2021-12-18 18:34:18 +00:00
pSprite - > cstat | = CSTAT_SPRITE_BLOOD_BIT1 | CSTAT_SPRITE_BLOCK_ALL ;
2020-12-02 19:22:13 +00:00
break ;
}
# else
pSprite - > clipdist = dudeInfo [ nType ] . clipdist ;
2021-12-18 18:34:18 +00:00
pSprite - > cstat | = CSTAT_SPRITE_BLOOD_BIT1 | CSTAT_SPRITE_BLOCK_ALL ;
2020-12-02 19:22:13 +00:00
# endif
2021-09-04 10:52:02 +00:00
act - > xvel = act - > yvel = act - > zvel = 0 ;
2020-12-02 19:22:13 +00:00
# ifdef NOONE_EXTENSIONS
// add a way to set custom hp for every enemy - should work only if map just started and not loaded.
if ( ! gModernMap | | pXSprite - > sysData2 < = 0 ) pXSprite - > health = dudeInfo [ nType ] . startHealth < < 4 ;
else pXSprite - > health = ClipRange ( pXSprite - > sysData2 < < 4 , 1 , 65535 ) ;
# else
pXSprite - > health = dudeInfo [ nType ] . startHealth < < 4 ;
# endif
}
2021-09-04 21:27:21 +00:00
if ( getSequence ( seqStartId ) ) seqSpawn ( seqStartId , act ) ;
2020-12-02 19:22:13 +00:00
}
aiInit ( ) ;
}
2019-09-19 22:42:45 +00:00
}
2020-12-02 19:22:13 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-12-03 20:36:32 +00:00
void actInit ( TArray < DBloodActor * > & actors )
2020-12-02 19:22:13 +00:00
{
2021-08-25 06:46:31 +00:00
# ifdef NOONE_EXTENSIONS
2020-12-02 19:22:13 +00:00
if ( ! gModernMap ) nnExtResetGlobals ( ) ;
2021-12-03 20:36:32 +00:00
else nnExtInitModernStuff ( actors ) ;
2021-08-25 06:46:31 +00:00
# endif
2020-12-02 19:22:13 +00:00
BloodStatIterator it ( kStatItem ) ;
while ( auto act = it . Next ( ) )
{
2021-12-21 22:18:23 +00:00
if ( act - > spr . type = = kItemWeaponVoodooDoll )
2020-12-02 19:22:13 +00:00
{
2021-12-21 22:18:23 +00:00
act - > spr . type = kItemAmmoVoodooDoll ;
2020-12-02 19:22:13 +00:00
break ;
}
}
actInitTraps ( ) ;
actInitThings ( ) ;
actInitDudes ( ) ;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-12-02 19:55:08 +00:00
static void ConcussSprite ( DBloodActor * source , DBloodActor * actor , int x , int y , int z , int damage )
2019-09-19 22:42:45 +00:00
{
2020-12-02 19:55:08 +00:00
auto pSprite = & actor - > s ( ) ;
int dx = pSprite - > x - x ;
int dy = pSprite - > y - y ;
int dz = ( pSprite - > z - z ) > > 4 ;
int dist2 = 0x40000 + dx * dx + dy * dy + dz * dz ;
assert ( dist2 > 0 ) ;
damage = scale ( 0x40000 , damage , dist2 ) ;
if ( pSprite - > flags & kPhysMove )
{
int mass = 0 ;
if ( actor - > IsDudeActor ( ) )
{
mass = getDudeInfo ( pSprite - > type ) - > mass ;
# ifdef NOONE_EXTENSIONS
if ( pSprite - > type = = kDudeModernCustom | | pSprite - > type = = kDudeModernCustomBurning )
{
2021-08-27 17:12:22 +00:00
mass = getSpriteMassBySize ( actor ) ;
2020-12-02 19:55:08 +00:00
}
# endif
}
else if ( pSprite - > type > = kThingBase & & pSprite - > type < kThingMax )
{
mass = thingInfo [ pSprite - > type - kThingBase ] . mass ;
}
else
{
2021-09-06 20:47:10 +00:00
Printf ( PRINT_HIGH , " Unexpected type in ConcussSprite(): Sprite: %d Type: %d Stat: %d " , actor - > GetIndex ( ) , ( int ) pSprite - > type , ( int ) pSprite - > statnum ) ;
2020-12-02 19:55:08 +00:00
return ;
}
2019-10-12 20:45:46 +00:00
2020-12-02 19:55:08 +00:00
if ( mass > 0 )
{
int size = ( tileWidth ( pSprite - > picnum ) * pSprite - > xrepeat * tileHeight ( pSprite - > picnum ) * pSprite - > yrepeat ) > > 1 ;
int t = scale ( damage , size , mass ) ;
2021-09-04 10:52:02 +00:00
actor - > xvel + = MulScale ( t , dx , 16 ) ;
actor - > yvel + = MulScale ( t , dy , 16 ) ;
actor - > zvel + = MulScale ( t , dz , 16 ) ;
2020-12-02 19:55:08 +00:00
}
}
2021-06-16 19:13:04 +00:00
actDamageSprite ( source , actor , kDamageExplode , damage ) ;
2019-09-19 22:42:45 +00:00
}
2020-12-02 19:55:08 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-11-21 08:45:50 +00:00
int actWallBounceVector ( int * x , int * y , walltype * pWall , int a4 )
2019-09-19 22:42:45 +00:00
{
2020-12-02 20:39:37 +00:00
int wx , wy ;
2021-11-21 08:45:50 +00:00
GetWallNormal ( pWall , & wx , & wy ) ;
2020-12-02 20:39:37 +00:00
int t = DMulScale ( * x , wx , * y , wy , 16 ) ;
2021-05-04 16:41:59 +00:00
int t2 = mulscale16r ( t , a4 + 0x10000 ) ;
2020-12-02 20:39:37 +00:00
* x - = MulScale ( wx , t2 , 16 ) ;
* y - = MulScale ( wy , t2 , 16 ) ;
2021-05-04 16:41:59 +00:00
return mulscale16r ( t , 0x10000 - a4 ) ;
2019-09-19 22:42:45 +00:00
}
2020-12-02 20:39:37 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-11-23 23:12:37 +00:00
int actFloorBounceVector ( int * x , int * y , int * z , sectortype * pSector , int a5 )
2019-09-19 22:42:45 +00:00
{
2021-05-04 16:41:59 +00:00
int t = 0x10000 - a5 ;
2021-11-19 19:35:33 +00:00
if ( pSector - > floorheinum = = 0 )
2020-12-02 20:39:37 +00:00
{
int t2 = MulScale ( * z , t , 16 ) ;
2021-05-04 16:41:59 +00:00
* z = - ( * z - t2 ) ;
2020-12-02 20:39:37 +00:00
return t2 ;
}
2021-11-19 19:35:33 +00:00
walltype * pWall = pSector - > firstWall ( ) ;
walltype * pWall2 = pWall - > point2Wall ( ) ;
2021-12-22 10:06:32 +00:00
int angle = getangle ( pWall2 - > pos . X - pWall - > pos . X , pWall2 - > pos . Y - pWall - > pos . Y ) + 512 ;
2021-11-19 19:35:33 +00:00
int t2 = pSector - > floorheinum < < 4 ;
2020-12-02 20:39:37 +00:00
int t3 = approxDist ( - 0x10000 , t2 ) ;
int t4 = DivScale ( - 0x10000 , t3 , 16 ) ;
int t5 = DivScale ( t2 , t3 , 16 ) ;
int t6 = MulScale ( t5 , Cos ( angle ) , 30 ) ;
int t7 = MulScale ( t5 , Sin ( angle ) , 30 ) ;
int t8 = TMulScale ( * x , t6 , * y , t7 , * z , t4 , 16 ) ;
2021-05-04 16:41:59 +00:00
int t9 = MulScale ( t8 , 0x10000 + a5 , 16 ) ;
2020-12-02 20:39:37 +00:00
* x - = MulScale ( t6 , t9 , 16 ) ;
* y - = MulScale ( t7 , t9 , 16 ) ;
* z - = MulScale ( t4 , t9 , 16 ) ;
return mulscale16r ( t8 , t ) ;
2019-09-19 22:42:45 +00:00
}
2020-12-02 20:39:37 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-11-23 23:49:29 +00:00
void actRadiusDamage ( DBloodActor * source , int x , int y , int z , sectortype * pSector , int nDist , int baseDmg , int distDmg , DAMAGE_TYPE dmgType , int flags , int burn )
2019-09-19 22:42:45 +00:00
{
2020-12-02 20:39:37 +00:00
auto pOwner = source - > GetOwner ( ) ;
2021-08-21 10:16:48 +00:00
const bool newSectCheckMethod = ! cl_bloodvanillaexplosions & & pOwner & & pOwner - > IsDudeActor ( ) & & ! VanillaMode ( ) ; // use new sector checking logic
2021-11-23 23:49:29 +00:00
auto sectorMap = GetClosestSpriteSectors ( pSector , x , y , nDist , nullptr , newSectCheckMethod ) ;
2020-12-02 20:39:37 +00:00
nDist < < = 4 ;
if ( flags & 2 )
{
BloodStatIterator it ( kStatDude ) ;
while ( auto act2 = it . Next ( ) )
{
if ( act2 ! = source | | ( flags & 1 ) )
{
auto pSprite2 = & act2 - > s ( ) ;
if ( act2 - > hasX ( ) )
{
if ( pSprite2 - > flags & 0x20 ) continue ;
2021-11-23 23:04:56 +00:00
if ( ! CheckSector ( sectorMap , pSprite2 ) ) continue ;
2021-11-23 23:52:54 +00:00
if ( ! CheckProximity ( act2 , x , y , z , pSector , nDist ) ) continue ;
2020-12-02 20:39:37 +00:00
int dx = abs ( x - pSprite2 - > x ) ;
int dy = abs ( y - pSprite2 - > y ) ;
int dz = abs ( z - pSprite2 - > z ) > > 4 ;
int dist = ksqrt ( dx * dx + dy * dy + dz * dz ) ;
if ( dist > nDist ) continue ;
int totaldmg ;
if ( dist ! = 0 ) totaldmg = baseDmg + ( ( nDist - dist ) * distDmg ) / nDist ;
else totaldmg = baseDmg + distDmg ;
actDamageSprite ( source , act2 , dmgType , totaldmg < < 4 ) ;
if ( burn ) actBurnSprite ( pOwner , act2 , burn ) ;
}
}
}
}
if ( flags & 4 )
{
BloodStatIterator it ( kStatDude ) ;
while ( auto act2 = it . Next ( ) )
{
auto pSprite2 = & act2 - > s ( ) ;
2019-10-20 14:50:47 +00:00
2020-12-02 20:39:37 +00:00
if ( pSprite2 - > flags & 0x20 ) continue ;
2021-11-23 23:04:56 +00:00
if ( ! CheckSector ( sectorMap , pSprite2 ) ) continue ;
2021-11-23 23:52:54 +00:00
if ( ! CheckProximity ( act2 , x , y , z , pSector , nDist ) ) continue ;
2020-12-02 20:39:37 +00:00
XSPRITE * pXSprite2 = & act2 - > x ( ) ;
if ( pXSprite2 - > locked ) continue ;
int dx = abs ( x - pSprite2 - > x ) ;
int dy = abs ( y - pSprite2 - > y ) ;
int dist = ksqrt ( dx * dx + dy * dy ) ;
if ( dist > nDist ) continue ;
int totaldmg ;
if ( dist ! = 0 ) totaldmg = baseDmg + ( ( nDist - dist ) * distDmg ) / nDist ;
else totaldmg = baseDmg + distDmg ;
actDamageSprite ( source , act2 , dmgType , totaldmg < < 4 ) ;
if ( burn ) actBurnSprite ( pOwner , act2 , burn ) ;
}
}
2019-09-19 22:42:45 +00:00
}
2020-12-02 21:33:14 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void actNapalmMove ( DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2020-12-02 21:33:14 +00:00
auto pXSprite = & actor - > x ( ) ;
auto pSprite = & actor - > s ( ) ;
auto pOwner = actor - > GetOwner ( ) ;
actPostSprite ( actor , kStatDecoration ) ;
seqSpawn ( 9 , actor ) ;
2021-12-18 15:02:15 +00:00
if ( Chance ( 0x8000 ) ) pSprite - > cstat | = CSTAT_SPRITE_XFLIP ;
2020-12-02 21:33:14 +00:00
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 303 , 24 + ( pSprite - > flags & 3 ) , 1 ) ;
2021-11-23 23:49:29 +00:00
actRadiusDamage ( pOwner , pSprite - > x , pSprite - > y , pSprite - > z , pSprite - > sector ( ) , 128 , 0 , 60 , kDamageExplode , 15 , 120 ) ;
2020-12-02 21:33:14 +00:00
if ( pXSprite - > data4 > 1 )
{
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_5 , nullptr , nullptr ) ;
2020-12-02 21:33:14 +00:00
int spawnparam [ 2 ] ;
spawnparam [ 0 ] = pXSprite - > data4 > > 1 ;
spawnparam [ 1 ] = pXSprite - > data4 - spawnparam [ 0 ] ;
int ang = pSprite - > ang ;
2021-09-04 10:52:02 +00:00
actor - > xvel = 0 ;
actor - > yvel = 0 ;
actor - > zvel = 0 ;
2020-12-02 21:33:14 +00:00
for ( int i = 0 ; i < 2 ; i + + )
{
int t1 = Random ( 0x33333 ) + 0x33333 ;
int rndang = Random2 ( 0x71 ) ;
pSprite - > ang = ( rndang + ang + 2048 ) & 2047 ;
auto spawned = actFireThing ( actor , 0 , 0 , - 0x93d0 , kThingNapalmBall , t1 ) ;
spawned - > SetOwner ( actor - > GetOwner ( ) ) ;
seqSpawn ( 61 , spawned , nNapalmClient ) ;
spawned - > x ( ) . data4 = spawnparam [ i ] ;
}
}
2019-09-19 22:42:45 +00:00
}
2020-12-02 21:33:14 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-05-04 16:41:59 +00:00
static DBloodActor * actSpawnFloor ( DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2020-12-02 22:39:38 +00:00
auto pSprite = & actor - > s ( ) ;
2021-11-23 23:55:57 +00:00
auto pSector = pSprite - > sector ( ) ;
2020-12-02 22:39:38 +00:00
int x = pSprite - > x ;
int y = pSprite - > y ;
2021-11-23 23:55:57 +00:00
updatesector ( x , y , & pSector ) ;
int zFloor = getflorzofslopeptr ( pSector , x , y ) ;
auto spawned = actSpawnSprite ( pSector , x , y , zFloor , 3 , 0 ) ;
2021-12-21 22:18:23 +00:00
if ( spawned ) spawned - > spr . cstat & = ~ CSTAT_SPRITE_BLOCK_ALL ;
2020-12-02 22:39:38 +00:00
return spawned ;
2019-09-19 22:42:45 +00:00
}
2021-05-04 16:41:59 +00:00
static DBloodActor * actDropAmmo ( DBloodActor * actor , int nType )
2019-09-19 22:42:45 +00:00
{
2020-12-02 22:39:38 +00:00
if ( ! actor ) return nullptr ;
auto pSprite = & actor - > s ( ) ;
if ( pSprite - > statnum < kMaxStatus & & nType > = kItemAmmoBase & & nType < kItemAmmoMax )
{
auto act2 = actSpawnFloor ( actor ) ;
2021-05-04 16:41:59 +00:00
const AMMOITEMDATA * pAmmo = & gAmmoItemData [ nType - kItemAmmoBase ] ;
2020-12-02 22:39:38 +00:00
auto pSprite2 = & act2 - > s ( ) ;
pSprite2 - > type = nType ;
pSprite2 - > picnum = pAmmo - > picnum ;
pSprite2 - > shade = pAmmo - > shade ;
pSprite2 - > xrepeat = pAmmo - > xrepeat ;
pSprite2 - > yrepeat = pAmmo - > yrepeat ;
return act2 ;
}
return nullptr ;
2019-09-19 22:42:45 +00:00
}
2021-05-04 16:41:59 +00:00
static DBloodActor * actDropWeapon ( DBloodActor * actor , int nType )
2019-09-19 22:42:45 +00:00
{
2020-12-02 22:39:38 +00:00
if ( ! actor ) return nullptr ;
auto pSprite = & actor - > s ( ) ;
if ( pSprite - > statnum < kMaxStatus & & nType > = kItemWeaponBase & & nType < kItemWeaponMax )
{
auto act2 = actSpawnFloor ( actor ) ;
2021-05-04 16:41:59 +00:00
const WEAPONITEMDATA * pWeapon = & gWeaponItemData [ nType - kItemWeaponBase ] ;
2020-12-02 22:39:38 +00:00
auto pSprite2 = & act2 - > s ( ) ;
pSprite2 - > type = nType ;
pSprite2 - > picnum = pWeapon - > picnum ;
pSprite2 - > shade = pWeapon - > shade ;
pSprite2 - > xrepeat = pWeapon - > xrepeat ;
pSprite2 - > yrepeat = pWeapon - > yrepeat ;
return act2 ;
}
return nullptr ;
2019-09-19 22:42:45 +00:00
}
2020-12-02 22:39:38 +00:00
static DBloodActor * actDropItem ( DBloodActor * actor , int nType )
2019-09-19 22:42:45 +00:00
{
2020-12-02 22:39:38 +00:00
if ( ! actor ) return nullptr ;
auto pSprite = & actor - > s ( ) ;
if ( pSprite - > statnum < kMaxStatus & & nType > = kItemBase & & nType < kItemMax )
{
auto act2 = actSpawnFloor ( actor ) ;
2021-05-04 16:41:59 +00:00
const ITEMDATA * pItem = & gItemData [ nType - kItemBase ] ;
2020-12-02 22:39:38 +00:00
auto pSprite2 = & act2 - > s ( ) ;
pSprite2 - > type = nType ;
pSprite2 - > picnum = pItem - > picnum ;
pSprite2 - > shade = pItem - > shade ;
pSprite2 - > xrepeat = pItem - > xrepeat ;
pSprite2 - > yrepeat = pItem - > yrepeat ;
return act2 ;
}
return nullptr ;
2019-09-19 22:42:45 +00:00
}
2020-12-02 22:39:38 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-05-04 16:41:59 +00:00
static DBloodActor * actDropKey ( DBloodActor * actor , int nType )
2019-09-19 22:42:45 +00:00
{
2020-12-02 22:39:38 +00:00
if ( ! actor ) return nullptr ;
auto pSprite = & actor - > s ( ) ;
if ( pSprite - > statnum < kMaxStatus & & nType > = kItemKeyBase & & nType < kItemKeyMax )
{
auto act2 = actDropItem ( actor , nType ) ;
if ( act2 & & gGameOptions . nGameType = = 1 )
{
act2 - > addX ( ) ;
act2 - > x ( ) . respawn = 3 ;
2021-11-26 13:03:21 +00:00
act2 - > hit . florhit . setNone ( ) ;
act2 - > hit . ceilhit . setNone ( ) ;
2020-12-02 22:39:38 +00:00
}
return act2 ;
}
return nullptr ;
2019-09-19 22:42:45 +00:00
}
2020-12-02 22:39:38 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-05-04 16:41:59 +00:00
static DBloodActor * actDropFlag ( DBloodActor * actor , int nType )
2019-09-19 22:42:45 +00:00
{
2020-12-02 22:39:38 +00:00
if ( ! actor ) return nullptr ;
auto pSprite = & actor - > s ( ) ;
if ( pSprite - > statnum < kMaxStatus & & ( nType = = 147 | | nType = = 148 ) )
{
auto act2 = actDropItem ( actor , nType ) ;
if ( act2 & & gGameOptions . nGameType = = 3 )
{
2021-08-27 07:44:47 +00:00
evPostActor ( act2 , 1800 , kCallbackReturnFlag ) ;
2020-12-02 22:39:38 +00:00
}
return act2 ;
}
return nullptr ;
2019-09-19 22:42:45 +00:00
}
2020-12-02 22:39:38 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-10-11 21:59:39 +00:00
2020-12-05 22:49:51 +00:00
DBloodActor * actDropObject ( DBloodActor * actor , int nType )
2020-12-02 22:39:38 +00:00
{
2021-05-04 16:41:59 +00:00
DBloodActor * act2 = nullptr ;
2020-12-02 23:30:19 +00:00
if ( nType > = kItemKeyBase & & nType < kItemKeyMax ) act2 = actDropKey ( actor , nType ) ;
else if ( nType = = kItemFlagA | | nType = = kItemFlagB ) act2 = actDropFlag ( actor , nType ) ;
else if ( nType > = kItemBase & & nType < kItemMax ) act2 = actDropItem ( actor , nType ) ;
else if ( nType > = kItemAmmoBase & & nType < kItemAmmoMax ) act2 = actDropAmmo ( actor , nType ) ;
else if ( nType > = kItemWeaponBase & & nType < kItemWeaponMax ) act2 = actDropWeapon ( actor , nType ) ;
2021-05-04 16:41:59 +00:00
if ( act2 )
2020-12-02 22:39:38 +00:00
{
int top , bottom ;
GetActorExtents ( act2 , & top , & bottom ) ;
2021-12-21 22:18:23 +00:00
if ( bottom > = act2 - > spr . z )
act2 - > spr . z - = bottom - act2 - > spr . z ;
2020-12-02 22:39:38 +00:00
}
return act2 ;
2019-09-19 22:42:45 +00:00
}
2020-12-02 22:39:38 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-05-04 16:41:59 +00:00
bool actHealDude ( DBloodActor * actor , int add , int threshold )
2019-09-19 22:42:45 +00:00
{
2020-12-02 23:00:03 +00:00
if ( ! actor ) return false ;
auto pXDude = & actor - > x ( ) ;
add < < = 4 ;
threshold < < = 4 ;
2021-05-11 22:48:41 +00:00
if ( pXDude - > health < ( unsigned ) threshold )
2021-05-04 16:41:59 +00:00
{
spritetype * pSprite = & actor - > s ( ) ;
2021-11-23 23:41:19 +00:00
if ( actor - > IsPlayerActor ( ) ) sfxPlay3DSound ( pSprite - > x , pSprite - > y , pSprite - > z , 780 , pSprite - > sector ( ) ) ;
2021-05-04 16:41:59 +00:00
pXDude - > health = min < uint32_t > ( pXDude - > health + add , threshold ) ;
2020-12-02 23:00:03 +00:00
return true ;
2021-05-04 16:41:59 +00:00
}
2020-12-02 23:00:03 +00:00
return false ;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-12-02 23:20:14 +00:00
2020-12-02 23:00:03 +00:00
# ifdef NOONE_EXTENSIONS
static bool actKillModernDude ( DBloodActor * actor , DAMAGE_TYPE damageType )
{
auto pSprite = & actor - > s ( ) ;
auto pXSprite = & actor - > x ( ) ;
2021-08-29 07:27:03 +00:00
GENDUDEEXTRA * pExtra = & actor - > genDudeExtra ;
2021-05-05 19:18:09 +00:00
removeDudeStuff ( actor ) ;
2021-05-06 06:39:33 +00:00
if ( pXSprite - > txID < = 0 | | getNextIncarnation ( actor ) = = nullptr )
2020-12-02 23:00:03 +00:00
{
2021-06-16 19:13:04 +00:00
if ( pExtra - > weaponType = = kGenDudeWeaponKamikaze & & Chance ( 0x4000 ) & & damageType ! = kDamageSpirit & & damageType ! = kDamageDrown )
2020-12-02 23:00:03 +00:00
{
2021-05-06 07:09:58 +00:00
doExplosion ( actor , pXSprite - > data1 - kTrapExploder ) ;
2021-09-16 19:10:23 +00:00
if ( Chance ( 0x9000 ) ) damageType = kDamageExplode ;
2021-05-04 16:41:59 +00:00
}
2020-12-02 23:00:03 +00:00
2021-06-16 19:13:04 +00:00
if ( damageType = = kDamageBurn )
2020-12-02 23:00:03 +00:00
{
2021-05-05 18:40:31 +00:00
if ( pExtra - > availDeaths [ kDamageBurn ] & & ! spriteIsUnderwater ( actor ) )
2020-12-02 23:00:03 +00:00
{
2021-05-04 16:41:59 +00:00
if ( pExtra - > canBurn )
2020-12-02 23:00:03 +00:00
{
2021-05-04 16:41:59 +00:00
pSprite - > type = kDudeModernCustomBurning ;
if ( pXSprite - > data2 = = kGenDudeDefaultSeq ) // don't inherit palette for burning if using default animation
pSprite - > pal = 0 ;
2021-08-31 19:52:26 +00:00
aiGenDudeNewState ( actor , & genDudeBurnGoto ) ;
2020-12-05 22:49:51 +00:00
actHealDude ( actor , dudeInfo [ 55 ] . startHealth , dudeInfo [ 55 ] . startHealth ) ;
2021-05-04 16:41:59 +00:00
if ( pXSprite - > burnTime < = 0 ) pXSprite - > burnTime = 1200 ;
2020-12-04 22:21:42 +00:00
actor - > dudeExtra . time = PlayClock + 360 ;
2020-12-02 23:00:03 +00:00
return true ;
2021-05-04 16:41:59 +00:00
}
2020-12-02 23:00:03 +00:00
}
2021-05-04 16:41:59 +00:00
else
2020-12-02 23:00:03 +00:00
{
2021-05-04 16:41:59 +00:00
pXSprite - > burnTime = 0 ;
2021-08-29 17:22:51 +00:00
actor - > SetBurnSource ( nullptr ) ;
2021-06-16 19:13:04 +00:00
damageType = kDamageFall ;
2020-12-02 23:00:03 +00:00
}
2021-05-04 16:41:59 +00:00
}
2020-12-02 23:00:03 +00:00
}
2021-05-04 16:41:59 +00:00
else
2020-12-02 23:00:03 +00:00
{
2021-05-04 16:41:59 +00:00
pXSprite - > locked = 1 ; // lock while transforming
2020-12-02 23:00:03 +00:00
2021-08-28 07:50:01 +00:00
aiSetGenIdleState ( actor ) ; // set idle state
2020-12-02 23:00:03 +00:00
2021-05-04 16:41:59 +00:00
if ( pXSprite - > key > 0 ) // drop keys
2020-12-05 22:49:51 +00:00
actDropObject ( actor , kItemKeyBase + pXSprite - > key - 1 ) ;
2020-12-02 23:00:03 +00:00
2021-05-04 16:41:59 +00:00
if ( pXSprite - > dropMsg > 0 ) // drop items
2020-12-05 22:49:51 +00:00
actDropObject ( actor , pXSprite - > dropMsg ) ;
2020-12-02 23:00:03 +00:00
2021-09-16 19:59:39 +00:00
pSprite - > flags & = ~ kPhysMove ;
2021-09-04 10:52:02 +00:00
actor - > xvel = actor - > yvel = 0 ;
2020-12-02 23:00:03 +00:00
2021-05-05 17:15:25 +00:00
playGenDudeSound ( actor , kGenDudeSndTransforming ) ;
2021-05-04 16:41:59 +00:00
int seqId = pXSprite - > data2 + kGenDudeSeqTransform ;
2020-12-02 23:00:03 +00:00
if ( getSequence ( seqId ) ) seqSpawn ( seqId , actor , - 1 ) ;
2021-05-04 16:41:59 +00:00
else
2020-12-02 23:00:03 +00:00
{
seqKill ( actor ) ;
2021-11-23 23:41:19 +00:00
DBloodActor * pEffectA = gFX . fxSpawnActor ( ( FX_ID ) 52 , pSprite - > sector ( ) , pSprite - > x , pSprite - > y , pSprite - > z , pSprite - > ang ) ;
2021-05-04 16:41:59 +00:00
if ( pEffectA ! = nullptr )
2020-12-02 23:00:03 +00:00
{
auto pEffect = & pEffectA - > s ( ) ;
2021-05-04 16:41:59 +00:00
pEffect - > cstat = CSTAT_SPRITE_ALIGNMENT_FACING ;
pEffect - > pal = 6 ;
pEffect - > xrepeat = pSprite - > xrepeat ;
pEffect - > yrepeat = pSprite - > yrepeat ;
}
2020-12-02 23:00:03 +00:00
2021-05-04 16:41:59 +00:00
GIBTYPE nGibType ;
for ( int i = 0 ; i < 3 ; i + + )
2020-12-02 23:00:03 +00:00
{
2021-05-04 16:41:59 +00:00
if ( Chance ( 0x3000 ) ) nGibType = GIBTYPE_6 ;
else if ( Chance ( 0x2000 ) ) nGibType = GIBTYPE_5 ;
else nGibType = GIBTYPE_17 ;
2020-12-02 23:00:03 +00:00
2021-05-04 16:41:59 +00:00
int top , bottom ;
2020-12-02 23:00:03 +00:00
GetActorExtents ( actor , & top , & bottom ) ;
2021-05-04 16:41:59 +00:00
CGibPosition gibPos ( pSprite - > x , pSprite - > y , top ) ;
2021-09-04 10:52:02 +00:00
CGibVelocity gibVel ( actor - > xvel > > 1 , actor - > yvel > > 1 , - 0xccccc ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( actor , nGibType , & gibPos , & gibVel ) ;
2020-12-02 23:00:03 +00:00
}
2021-05-04 16:41:59 +00:00
}
2020-12-02 23:00:03 +00:00
2021-05-04 16:41:59 +00:00
pXSprite - > sysData1 = kGenDudeTransformStatus ; // in transform
2020-12-02 23:00:03 +00:00
return true ;
2021-05-04 16:41:59 +00:00
}
2020-12-02 23:00:03 +00:00
return false ;
2019-09-19 22:42:45 +00:00
}
2020-12-02 23:00:03 +00:00
# endif
2019-09-19 22:42:45 +00:00
2020-12-02 23:20:14 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-05-04 16:41:59 +00:00
static bool actKillDudeStage1 ( DBloodActor * actor , DAMAGE_TYPE damageType )
2019-09-19 22:42:45 +00:00
{
2020-12-02 23:20:14 +00:00
auto pSprite = & actor - > s ( ) ;
auto pXSprite = & actor - > x ( ) ;
switch ( pSprite - > type )
{
# ifdef NOONE_EXTENSIONS
case kDudeModernCustom :
if ( actKillModernDude ( actor , damageType ) ) return true ;
break ;
# endif
case kDudeCerberusTwoHead : // Cerberus
seqSpawn ( dudeInfo [ pSprite - > type - kDudeBase ] . seqStartID + 1 , actor , - 1 ) ;
return true ;
2019-10-11 21:59:39 +00:00
2020-12-02 23:20:14 +00:00
case kDudeCultistTommy :
case kDudeCultistShotgun :
case kDudeCultistTesla :
case kDudeCultistTNT :
2021-06-16 19:13:04 +00:00
if ( damageType = = kDamageBurn & & pXSprite - > medium = = kMediumNormal )
2020-12-02 23:20:14 +00:00
{
pSprite - > type = kDudeBurningCultist ;
aiNewState ( actor , & cultistBurnGoto ) ;
actHealDude ( actor , dudeInfo [ 40 ] . startHealth , dudeInfo [ 40 ] . startHealth ) ;
return true ;
}
break ;
2019-09-19 22:42:45 +00:00
2020-12-02 23:20:14 +00:00
case kDudeBeast :
2021-06-16 19:13:04 +00:00
if ( damageType = = kDamageBurn & & pXSprite - > medium = = kMediumNormal )
2020-12-02 23:20:14 +00:00
{
pSprite - > type = kDudeBurningBeast ;
aiNewState ( actor , & beastBurnGoto ) ;
actHealDude ( actor , dudeInfo [ 53 ] . startHealth , dudeInfo [ 53 ] . startHealth ) ;
return true ;
}
break ;
2019-10-11 21:59:39 +00:00
2020-12-02 23:20:14 +00:00
case kDudeInnocent :
2021-06-16 19:13:04 +00:00
if ( damageType = = kDamageBurn & & pXSprite - > medium = = kMediumNormal )
2020-12-02 23:20:14 +00:00
{
pSprite - > type = kDudeBurningInnocent ;
aiNewState ( actor , & innocentBurnGoto ) ;
actHealDude ( actor , dudeInfo [ 39 ] . startHealth , dudeInfo [ 39 ] . startHealth ) ;
return true ;
}
break ;
2021-08-15 07:12:33 +00:00
case kDudeTinyCaleb :
2021-08-21 10:16:48 +00:00
if ( cl_bloodvanillaenemies | | VanillaMode ( ) )
2021-08-15 07:12:33 +00:00
break ;
if ( damageType = = kDamageBurn & & pXSprite - > medium = = kMediumNormal )
{
pSprite - > type = kDudeBurningTinyCaleb ;
2021-08-15 07:32:00 +00:00
aiNewState ( actor , & tinycalebBurnGoto ) ;
2021-08-15 07:12:33 +00:00
actHealDude ( actor , dudeInfo [ 39 ] . startHealth , dudeInfo [ 39 ] . startHealth ) ;
return true ;
}
break ;
2020-12-02 23:20:14 +00:00
}
return false ;
}
2019-09-19 22:42:45 +00:00
2020-12-02 23:20:14 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-09-19 22:42:45 +00:00
2020-12-02 23:20:14 +00:00
static void checkAddFrag ( DBloodActor * killerActor , DBloodActor * actor )
{
auto pKillerSprite = & killerActor - > s ( ) ;
auto pSprite = & actor - > s ( ) ;
if ( VanillaMode ( ) )
{
if ( killerActor - > IsPlayerActor ( ) )
{
PLAYER * pPlayer = & gPlayer [ pKillerSprite - > type - kDudePlayer1 ] ;
if ( gGameOptions . nGameType = = 1 )
pPlayer - > fragCount + + ;
}
}
else if ( gGameOptions . nGameType = = 1 & & killerActor - > IsPlayerActor ( ) & & pSprite - > statnum = = kStatDude )
{
switch ( pSprite - > type )
{
case kDudeBat :
case kDudeRat :
case kDudeInnocent :
case kDudeBurningInnocent :
break ;
default :
PLAYER * pKillerPlayer = & gPlayer [ pKillerSprite - > type - kDudePlayer1 ] ;
pKillerPlayer - > fragCount + + ;
break ;
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void checkDropObjects ( DBloodActor * actor )
{
auto pXSprite = & actor - > x ( ) ;
if ( pXSprite - > key > 0 ) actDropObject ( actor , kItemKeyBase + pXSprite - > key - 1 ) ;
if ( pXSprite - > dropMsg > 0 ) actDropObject ( actor , pXSprite - > dropMsg ) ;
2021-12-21 22:18:23 +00:00
switch ( actor - > spr . type )
2020-12-02 23:20:14 +00:00
{
case kDudeCultistTommy :
{
int nRand = Random ( 100 ) ;
if ( nRand < 10 ) actDropObject ( actor , kItemWeaponTommygun ) ;
else if ( nRand < 50 ) actDropObject ( actor , kItemAmmoTommygunFew ) ;
break ;
}
case kDudeCultistShotgun :
{
int nRand = Random ( 100 ) ;
if ( nRand < = 10 ) actDropObject ( actor , kItemWeaponSawedoff ) ;
else if ( nRand < = 50 ) actDropObject ( actor , kItemAmmoSawedoffFew ) ;
break ;
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static int checkDamageType ( DBloodActor * actor , DAMAGE_TYPE damageType )
{
int nSeq ;
auto pSprite = & actor - > s ( ) ;
switch ( damageType )
{
2021-06-16 19:13:04 +00:00
case kDamageExplode :
2020-12-02 23:20:14 +00:00
nSeq = 2 ;
2021-05-04 16:41:59 +00:00
switch ( pSprite - > type )
2020-12-02 23:20:14 +00:00
{
2020-01-26 11:19:01 +00:00
# ifdef NOONE_EXTENSIONS
2020-12-02 23:20:14 +00:00
case kDudeModernCustom :
2021-05-04 16:41:59 +00:00
case kDudeModernCustomBurning :
2020-12-02 23:20:14 +00:00
{
2021-05-05 17:15:25 +00:00
playGenDudeSound ( actor , kGenDudeSndDeathExplode ) ;
2021-08-29 07:27:03 +00:00
GENDUDEEXTRA * pExtra = & actor - > genDudeExtra ;
2021-05-04 16:41:59 +00:00
if ( ! pExtra - > availDeaths [ damageType ] )
2020-12-02 23:20:14 +00:00
{
nSeq = 1 ;
2021-06-16 19:13:04 +00:00
damageType = kDamageFall ;
2020-12-02 23:20:14 +00:00
}
break ;
}
# endif
case kDudeCultistTommy :
case kDudeCultistShotgun :
case kDudeCultistTommyProne :
case kDudeBurningInnocent :
case kDudeBurningCultist :
case kDudeInnocent :
case kDudeCultistShotgunProne :
case kDudeCultistTesla :
case kDudeCultistTNT :
case kDudeCultistBeast :
case kDudeTinyCaleb :
case kDudeBurningTinyCaleb :
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 717 , - 1 , 0 ) ;
2020-12-02 23:20:14 +00:00
break ;
}
break ;
2021-06-16 19:13:04 +00:00
case kDamageBurn :
2020-12-02 23:20:14 +00:00
nSeq = 3 ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 351 , - 1 , 0 ) ;
2020-12-02 23:20:14 +00:00
break ;
2021-06-16 19:13:04 +00:00
case kDamageSpirit :
2020-12-02 23:20:14 +00:00
switch ( pSprite - > type ) {
case kDudeZombieAxeNormal :
case kDudeZombieAxeBuried :
nSeq = 14 ;
break ;
case kDudeZombieButcher :
nSeq = 11 ;
break ;
default :
nSeq = 1 ;
break ;
}
break ;
2021-06-16 19:13:04 +00:00
case kDamageFall :
2020-12-02 23:20:14 +00:00
switch ( pSprite - > type )
{
case kDudeCultistTommy :
case kDudeCultistShotgun :
nSeq = 1 ;
break ;
default :
nSeq = 1 ;
break ;
}
break ;
default :
nSeq = 1 ;
break ;
}
return nSeq ;
}
2019-09-19 22:42:45 +00:00
2020-12-02 23:20:14 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-09-19 22:42:45 +00:00
2020-12-02 23:20:14 +00:00
static void spawnGibs ( DBloodActor * actor , int type , int velz )
{
int top , bottom ;
GetActorExtents ( actor , & top , & bottom ) ;
2021-12-21 22:18:23 +00:00
CGibPosition gibPos ( actor - > spr . x , actor - > spr . y , top ) ;
2021-09-04 10:52:02 +00:00
CGibVelocity gibVel ( actor - > xvel > > 1 , actor - > yvel > > 1 , velz ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_27 , & gibPos , & gibVel ) ;
2020-12-02 23:20:14 +00:00
}
2019-09-19 22:42:45 +00:00
2020-12-02 23:20:14 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void zombieAxeNormalDeath ( DBloodActor * actor , int nSeq )
{
auto pSprite = & actor - > s ( ) ;
int nType = pSprite - > type - kDudeBase ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 1107 + Random ( 2 ) , - 1 , 0 ) ;
2020-12-02 23:20:14 +00:00
if ( nSeq = = 2 )
{
seqSpawn ( dudeInfo [ nType ] . seqStartID + nSeq , actor , nDudeToGibClient1 ) ;
2021-05-04 16:41:59 +00:00
spawnGibs ( actor , GIBTYPE_27 , - 0xccccc ) ;
2020-12-02 23:20:14 +00:00
}
else if ( nSeq = = 1 & & Chance ( 0x4000 ) )
{
seqSpawn ( dudeInfo [ nType ] . seqStartID + 7 , actor , nDudeToGibClient1 ) ;
2021-08-27 07:44:47 +00:00
evPostActor ( actor , 0 , kCallbackFXZombieSpurt ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 362 , - 1 , 0 ) ;
2020-12-02 23:20:14 +00:00
actor - > x ( ) . data1 = 35 ;
actor - > x ( ) . data2 = 5 ;
2021-05-04 16:41:59 +00:00
spawnGibs ( actor , GIBTYPE_27 , - 0x111111 ) ;
2020-12-02 23:20:14 +00:00
}
else if ( nSeq = = 14 ) seqSpawn ( dudeInfo [ nType ] . seqStartID + nSeq , actor , - 1 ) ;
else if ( nSeq = = 3 ) seqSpawn ( dudeInfo [ nType ] . seqStartID + 13 , actor , nDudeToGibClient2 ) ;
else seqSpawn ( dudeInfo [ nType ] . seqStartID + nSeq , actor , nDudeToGibClient1 ) ;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void burningCultistDeath ( DBloodActor * actor , int nSeq )
{
auto pSprite = & actor - > s ( ) ;
2021-09-16 19:34:16 +00:00
if ( Chance ( 0x4000 ) & & nSeq = = 3 ) sfxPlay3DSound ( actor , 718 , - 1 , 0 ) ;
else sfxPlay3DSound ( actor , 1018 + Random ( 2 ) , - 1 , 0 ) ;
2020-12-02 23:20:14 +00:00
int nType = pSprite - > type - kDudeBase ;
if ( Chance ( 0x8000 ) )
{
for ( int i = 0 ; i < 3 ; i + + )
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_7 , nullptr , nullptr ) ;
2020-12-02 23:20:14 +00:00
seqSpawn ( dudeInfo [ nType ] . seqStartID + 16 - Random ( 1 ) , actor , nDudeToGibClient1 ) ;
}
else
seqSpawn ( dudeInfo [ nType ] . seqStartID + 15 , actor , nDudeToGibClient2 ) ;
}
# ifdef NOONE_EXTENSIONS
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void modernCustomDudeDeath ( DBloodActor * actor , int nSeq , int damageType )
{
auto pXSprite = & actor - > x ( ) ;
2021-05-05 17:15:25 +00:00
playGenDudeSound ( actor , kGenDudeSndDeathNormal ) ;
2021-08-30 18:21:49 +00:00
int dudeToGib = ( actCheckRespawn ( actor ) ) ? - 1 : ( ( nSeq = = 3 ) ? nDudeToGibClient2 : nDudeToGibClient1 ) ;
2021-05-04 16:41:59 +00:00
if ( nSeq = = 3 )
2020-12-02 23:20:14 +00:00
{
2021-08-29 07:27:03 +00:00
GENDUDEEXTRA * pExtra = & actor - > genDudeExtra ;
2020-12-02 23:20:14 +00:00
if ( pExtra - > availDeaths [ kDmgBurn ] = = 3 ) seqSpawn ( ( 15 + Random ( 2 ) ) + pXSprite - > data2 , actor , dudeToGib ) ;
else if ( pExtra - > availDeaths [ kDmgBurn ] = = 2 ) seqSpawn ( 16 + pXSprite - > data2 , actor , dudeToGib ) ;
else if ( pExtra - > availDeaths [ kDmgBurn ] = = 1 ) seqSpawn ( 15 + pXSprite - > data2 , actor , dudeToGib ) ;
else if ( getSequence ( pXSprite - > data2 + nSeq ) ) seqSpawn ( nSeq + pXSprite - > data2 , actor , dudeToGib ) ;
else seqSpawn ( 1 + pXSprite - > data2 , actor , dudeToGib ) ;
}
2021-05-04 16:41:59 +00:00
else
2020-12-02 23:20:14 +00:00
{
seqSpawn ( nSeq + pXSprite - > data2 , actor , dudeToGib ) ;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void modernCustomDudeBurningDeath ( DBloodActor * actor , int nSeq )
{
2021-05-05 17:15:25 +00:00
playGenDudeSound ( actor , kGenDudeSndDeathExplode ) ;
2021-08-30 18:21:49 +00:00
int dudeToGib = ( actCheckRespawn ( actor ) ) ? - 1 : nDudeToGibClient1 ;
2020-12-02 23:20:14 +00:00
if ( Chance ( 0x4000 ) ) spawnGibs ( actor , GIBTYPE_27 , - 0xccccc ) ;
2021-08-29 07:27:03 +00:00
GENDUDEEXTRA * pExtra = & actor - > genDudeExtra ;
2020-12-02 23:20:14 +00:00
int seqofs = actor - > x ( ) . data2 ;
if ( pExtra - > availDeaths [ kDmgBurn ] = = 3 ) seqSpawn ( ( 15 + Random ( 2 ) ) + seqofs , actor , dudeToGib ) ;
else if ( pExtra - > availDeaths [ kDmgBurn ] = = 2 ) seqSpawn ( 16 + seqofs , actor , dudeToGib ) ;
else if ( pExtra - > availDeaths [ kDmgBurn ] = = 1 ) seqSpawn ( 15 + seqofs , actor , dudeToGib ) ;
else seqSpawn ( 1 + seqofs , actor , dudeToGib ) ;
}
2020-01-26 11:19:01 +00:00
# endif
2020-12-02 23:20:14 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void zombieAxeBurningDeath ( DBloodActor * actor , int nSeq )
{
auto pSprite = & actor - > s ( ) ;
int nType = pSprite - > type - kDudeBase ;
if ( Chance ( 0x8000 ) & & nSeq = = 3 )
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 1109 , - 1 , 0 ) ;
2020-12-02 23:20:14 +00:00
else
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 1107 + Random ( 2 ) , - 1 , 0 ) ;
2020-12-02 23:20:14 +00:00
if ( Chance ( 0x8000 ) )
{
seqSpawn ( dudeInfo [ nType ] . seqStartID + 13 , actor , nDudeToGibClient1 ) ;
spawnGibs ( actor , GIBTYPE_27 , - 0xccccc ) ;
}
else
seqSpawn ( dudeInfo [ nType ] . seqStartID + 13 , actor , nDudeToGibClient2 ) ;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void zombieButcherDeath ( DBloodActor * actor , int nSeq )
{
auto pSprite = & actor - > s ( ) ;
int nType = pSprite - > type - kDudeBase ;
if ( nSeq = = 14 )
{
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 1206 , - 1 , 0 ) ;
2020-12-02 23:20:14 +00:00
seqSpawn ( dudeInfo [ nType ] . seqStartID + 11 , actor , - 1 ) ;
return ;
}
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 1204 + Random ( 2 ) , - 1 , 0 ) ;
2020-12-02 23:20:14 +00:00
if ( nSeq = = 3 )
seqSpawn ( dudeInfo [ nType ] . seqStartID + 10 , actor , - 1 ) ;
else
seqSpawn ( dudeInfo [ nType ] . seqStartID + nSeq , actor , - 1 ) ;
2019-09-19 22:42:45 +00:00
}
2020-12-02 23:20:14 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void genericDeath ( DBloodActor * actor , int nSeq , int sound1 , int seqnum )
{
2021-09-16 19:34:16 +00:00
if ( Chance ( 0x4000 ) & & nSeq = = 3 ) sfxPlay3DSound ( actor , sound1 + 2 , - 1 , 0 ) ;
else sfxPlay3DSound ( actor , sound1 + Random ( 2 ) , - 1 , 0 ) ;
2021-05-04 16:41:59 +00:00
seqSpawn ( seqnum , actor , - 1 ) ;
2020-12-02 23:20:14 +00:00
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void actKillDude ( DBloodActor * killerActor , DBloodActor * actor , DAMAGE_TYPE damageType , int damage )
{
2021-05-04 16:41:59 +00:00
auto pSprite = & actor - > s ( ) ;
assert ( pSprite - > type > = kDudeBase & & pSprite - > type < kDudeMax & & actor - > hasX ( ) ) ;
int nType = pSprite - > type - kDudeBase ;
2020-12-02 23:20:14 +00:00
if ( actKillDudeStage1 ( actor , damageType ) ) return ;
for ( int p = connecthead ; p > = 0 ; p = connectpoint2 [ p ] )
{
2021-09-04 19:59:34 +00:00
if ( gPlayer [ p ] . fragger = = actor & & gPlayer [ p ] . deathTime > 0 )
gPlayer [ p ] . fragger = nullptr ;
2020-12-02 23:20:14 +00:00
}
if ( pSprite - > type ! = kDudeCultistBeast )
2020-12-03 17:00:07 +00:00
trTriggerSprite ( actor , kCmdOff ) ;
2020-12-02 23:20:14 +00:00
pSprite - > flags | = 7 ;
checkAddFrag ( killerActor , actor ) ;
checkDropObjects ( actor ) ;
int nSeq = checkDamageType ( actor , damageType ) ;
2021-05-04 16:41:59 +00:00
if ( ! getSequence ( getDudeInfo ( nType + kDudeBase ) - > seqStartID + nSeq ) )
2020-12-02 23:20:14 +00:00
{
seqKill ( actor ) ;
gKillMgr . AddKill ( pSprite ) ;
actPostSprite ( actor , kStatFree ) ;
return ;
}
2020-12-04 22:21:42 +00:00
auto Owner = actor - > GetOwner ( ) ;
2021-08-25 06:46:31 +00:00
switch ( pSprite - > type )
2020-12-02 23:20:14 +00:00
{
case kDudeZombieAxeNormal :
zombieAxeNormalDeath ( actor , nSeq ) ;
break ;
case kDudeCultistTommy :
case kDudeCultistShotgun :
case kDudeCultistTesla :
case kDudeCultistTNT :
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 1018 + Random ( 2 ) , - 1 , 0 ) ;
2021-05-04 16:41:59 +00:00
seqSpawn ( dudeInfo [ nType ] . seqStartID + nSeq , actor , nSeq = = 3 ? nDudeToGibClient2 : nDudeToGibClient1 ) ;
2020-12-02 23:20:14 +00:00
break ;
case kDudeBurningCultist :
burningCultistDeath ( actor , nSeq ) ;
2021-06-16 19:13:04 +00:00
damageType = kDamageExplode ;
2020-12-02 23:20:14 +00:00
break ;
# ifdef NOONE_EXTENSIONS
case kDudeModernCustom :
modernCustomDudeDeath ( actor , nSeq , damageType ) ;
2021-05-06 08:55:56 +00:00
genDudePostDeath ( actor , damageType , damage ) ;
2020-12-02 23:20:14 +00:00
return ;
case kDudeModernCustomBurning :
modernCustomDudeBurningDeath ( actor , nSeq ) ;
2021-05-06 08:55:56 +00:00
genDudePostDeath ( actor , kDamageExplode , damage ) ;
2020-12-02 23:20:14 +00:00
return ;
# endif
case kDudeBurningZombieAxe :
zombieAxeBurningDeath ( actor , nSeq ) ;
2021-06-16 19:13:04 +00:00
damageType = kDamageExplode ;
2020-12-02 23:20:14 +00:00
break ;
case kDudeBurningZombieButcher :
genericDeath ( actor , nSeq , 1204 , dudeInfo [ 4 ] . seqStartID + 10 ) ;
break ;
case kDudeBurningInnocent :
2021-06-16 19:13:04 +00:00
damageType = kDamageExplode ;
2021-05-04 16:41:59 +00:00
seqSpawn ( dudeInfo [ nType ] . seqStartID + 7 , actor , nDudeToGibClient1 ) ;
2020-12-02 23:20:14 +00:00
break ;
case kDudeZombieButcher :
zombieButcherDeath ( actor , nSeq ) ;
break ;
case kDudeGargoyleFlesh :
genericDeath ( actor , nSeq , 1403 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudeGargoyleStone :
genericDeath ( actor , nSeq , 1453 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudePhantasm :
genericDeath ( actor , nSeq , 1603 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudeHellHound :
genericDeath ( actor , nSeq , 1303 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudeHand :
genericDeath ( actor , nSeq , 1903 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudeSpiderBrown :
2021-10-06 20:20:57 +00:00
if ( Owner ) Owner - > dudeExtra . stats . birthCounter - - ;
2020-12-02 23:20:14 +00:00
genericDeath ( actor , nSeq , 1803 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudeSpiderRed :
2021-10-06 20:20:57 +00:00
if ( Owner ) Owner - > dudeExtra . stats . birthCounter - - ;
2020-12-02 23:20:14 +00:00
genericDeath ( actor , nSeq , 1803 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudeSpiderBlack :
2021-10-06 20:20:57 +00:00
if ( Owner ) Owner - > dudeExtra . stats . birthCounter - - ;
2020-12-02 23:20:14 +00:00
genericDeath ( actor , nSeq , 1803 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudeSpiderMother :
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 1850 , - 1 , 0 ) ;
2021-05-04 16:41:59 +00:00
seqSpawn ( dudeInfo [ nType ] . seqStartID + nSeq , actor , - 1 ) ;
2020-12-02 23:20:14 +00:00
break ;
case kDudeGillBeast :
genericDeath ( actor , nSeq , 1703 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudeBoneEel :
genericDeath ( actor , nSeq , 1503 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudeBat :
genericDeath ( actor , nSeq , 2003 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudeRat :
genericDeath ( actor , nSeq , 2103 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudePodGreen :
case kDudeTentacleGreen :
case kDudePodFire :
case kDudeTentacleFire :
if ( ( pSprite - > cstat & CSTAT_SPRITE_YFLIP ) ) pSprite - > cstat & = ~ CSTAT_SPRITE_YFLIP ;
2021-05-04 16:41:59 +00:00
switch ( pSprite - > type )
2020-12-02 23:20:14 +00:00
{
case kDudePodGreen :
genericDeath ( actor , nSeq , 2203 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudeTentacleGreen :
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , damage = = 5 ? 2471 : 2472 , - 1 , 0 ) ;
2020-12-02 23:20:14 +00:00
seqSpawn ( dudeInfo [ nType ] . seqStartID + nSeq , actor , - 1 ) ;
break ;
case kDudePodFire :
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , damage = = 5 ? 2451 : 2452 , - 1 , 0 ) ;
2020-12-02 23:20:14 +00:00
seqSpawn ( dudeInfo [ nType ] . seqStartID + nSeq , actor , - 1 ) ;
break ;
case kDudeTentacleFire :
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 2501 , - 1 , 0 ) ;
2020-12-02 23:20:14 +00:00
seqSpawn ( dudeInfo [ nType ] . seqStartID + nSeq , actor , - 1 ) ;
break ;
}
break ;
case kDudePodMother :
case kDudeTentacleMother :
genericDeath ( actor , nSeq , 2203 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudeCerberusTwoHead :
case kDudeCerberusOneHead :
genericDeath ( actor , nSeq , 2303 , dudeInfo [ nType ] . seqStartID + nSeq ) ;
break ;
case kDudeTchernobog :
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 2380 , - 1 , 0 ) ;
2021-05-04 16:41:59 +00:00
seqSpawn ( dudeInfo [ nType ] . seqStartID + nSeq , actor , - 1 ) ;
2020-12-02 23:20:14 +00:00
break ;
case kDudeBurningTinyCaleb :
2021-06-16 19:13:04 +00:00
damageType = kDamageExplode ;
2021-05-04 16:41:59 +00:00
seqSpawn ( dudeInfo [ nType ] . seqStartID + 11 , actor , nDudeToGibClient1 ) ;
2020-12-02 23:20:14 +00:00
break ;
case kDudeBeast :
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 9000 + Random ( 2 ) , - 1 , 0 ) ;
2021-05-04 16:41:59 +00:00
seqSpawn ( dudeInfo [ nType ] . seqStartID + nSeq , actor , nSeq = = 3 ? nDudeToGibClient2 : nDudeToGibClient1 ) ;
2020-12-02 23:20:14 +00:00
break ;
case kDudeBurningBeast :
2021-06-16 19:13:04 +00:00
damageType = kDamageExplode ;
2021-05-04 16:41:59 +00:00
seqSpawn ( dudeInfo [ nType ] . seqStartID + 12 , actor , nDudeToGibClient1 ) ;
2020-12-02 23:20:14 +00:00
break ;
default :
2021-05-04 16:41:59 +00:00
seqSpawn ( getDudeInfo ( nType + kDudeBase ) - > seqStartID + nSeq , actor , - 1 ) ;
2020-12-02 23:20:14 +00:00
break ;
}
2021-05-04 16:41:59 +00:00
2021-06-16 19:13:04 +00:00
if ( damageType = = kDamageExplode )
2020-12-02 23:20:14 +00:00
{
2021-05-04 16:41:59 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( pSprite - > type ) ;
2020-12-02 23:20:14 +00:00
for ( int i = 0 ; i < 3 ; i + + )
if ( pDudeInfo - > nGibType [ i ] > - 1 )
2021-08-29 20:22:16 +00:00
GibSprite ( actor , ( GIBTYPE ) pDudeInfo - > nGibType [ i ] , nullptr , nullptr ) ;
2020-12-02 23:20:14 +00:00
for ( int i = 0 ; i < 4 ; i + + )
2021-08-26 22:07:33 +00:00
fxSpawnBlood ( actor , damage ) ;
2020-12-02 23:20:14 +00:00
}
gKillMgr . AddKill ( pSprite ) ;
2021-08-30 18:21:49 +00:00
actCheckRespawn ( actor ) ;
2020-12-02 23:20:14 +00:00
pSprite - > type = kThingBloodChunks ;
actPostSprite ( actor , kStatThing ) ;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-12-02 23:30:19 +00:00
static int actDamageDude ( DBloodActor * source , DBloodActor * actor , int damage , DAMAGE_TYPE damageType )
{
auto pSprite = & actor - > s ( ) ;
XSPRITE * pXSprite = & actor - > x ( ) ;
2019-10-20 14:50:47 +00:00
2020-12-02 23:30:19 +00:00
if ( ! actor - > IsDudeActor ( ) )
{
Printf ( PRINT_HIGH , " Bad Dude Failed: initial=%d type=%d %s \n " , ( int ) pSprite - > inittype , ( int ) pSprite - > type , ( int ) ( pSprite - > flags & kHitagRespawn ) ? " RESPAWN " : " NORMAL " ) ;
return damage > > 4 ;
//I_Error("Bad Dude Failed: initial=%d type=%d %s\n", (int)pSprite->inittype, (int)pSprite->type, (int)(pSprite->flags & 16) ? "RESPAWN" : "NORMAL");
}
2019-10-12 20:45:46 +00:00
2020-12-02 23:30:19 +00:00
int nType = pSprite - > type - kDudeBase ;
int nDamageFactor = getDudeInfo ( nType + kDudeBase ) - > damageVal [ damageType ] ;
# ifdef NOONE_EXTENSIONS
if ( pSprite - > type = = kDudeModernCustom )
2021-08-29 07:27:03 +00:00
nDamageFactor = actor - > genDudeExtra . dmgControl [ damageType ] ;
2020-12-02 23:30:19 +00:00
# endif
2019-10-20 14:50:47 +00:00
2020-12-02 23:30:19 +00:00
if ( ! nDamageFactor ) return 0 ;
else if ( nDamageFactor ! = 256 ) damage = MulScale ( damage , nDamageFactor , 8 ) ;
2019-11-08 19:57:01 +00:00
2021-08-29 07:44:08 +00:00
if ( ! actor - > IsPlayerActor ( ) )
2020-12-02 23:30:19 +00:00
{
if ( pXSprite - > health < = 0 ) return 0 ;
damage = aiDamageSprite ( source , actor , damageType , damage ) ;
if ( pXSprite - > health < = 0 )
2021-06-16 19:13:04 +00:00
actKillDude ( source , actor , ( ( damageType = = kDamageExplode & & damage < 160 ) ? kDamageFall : damageType ) , damage ) ;
2020-12-02 23:30:19 +00:00
}
else
{
PLAYER * pPlayer = & gPlayer [ pSprite - > type - kDudePlayer1 ] ;
if ( pXSprite - > health > 0 | | playerSeqPlaying ( pPlayer , 16 ) )
damage = playerDamageSprite ( source , pPlayer , damageType , damage ) ;
2019-10-12 20:45:46 +00:00
2020-12-02 23:30:19 +00:00
}
return damage ;
}
2019-10-12 20:45:46 +00:00
2020-12-02 23:30:19 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-10-12 20:45:46 +00:00
2020-12-02 23:30:19 +00:00
static int actDamageThing ( DBloodActor * source , DBloodActor * actor , int damage , DAMAGE_TYPE damageType , PLAYER * pSourcePlayer )
{
auto pSprite = & actor - > s ( ) ;
XSPRITE * pXSprite = & actor - > x ( ) ;
2019-09-19 22:42:45 +00:00
2020-12-02 23:30:19 +00:00
assert ( pSprite - > type > = kThingBase & & pSprite - > type < kThingMax ) ;
int nType = pSprite - > type - kThingBase ;
int nDamageFactor = thingInfo [ nType ] . dmgControl [ damageType ] ;
2020-01-26 11:19:01 +00:00
2020-12-02 23:30:19 +00:00
if ( ! nDamageFactor ) return 0 ;
else if ( nDamageFactor ! = 256 ) damage = MulScale ( damage , nDamageFactor , 8 ) ;
2019-10-11 21:59:39 +00:00
2020-12-02 23:30:19 +00:00
pXSprite - > health = ClipLow ( pXSprite - > health - damage , 0 ) ;
if ( pXSprite - > health < = 0 )
{
auto Owner = actor - > GetOwner ( ) ;
switch ( pSprite - > type )
{
case kThingDroppedLifeLeech :
# ifdef NOONE_EXTENSIONS
case kModernThingEnemyLifeLeech :
# endif
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_14 , nullptr , nullptr ) ;
2020-12-02 23:30:19 +00:00
pXSprite - > data1 = pXSprite - > data2 = pXSprite - > data3 = pXSprite - > DudeLockout = 0 ;
pXSprite - > stateTimer = pXSprite - > data4 = pXSprite - > isTriggered = 0 ;
# ifdef NOONE_EXTENSIONS
2021-12-21 22:18:23 +00:00
if ( Owner & & Owner - > spr . type = = kDudeModernCustom )
2020-12-02 23:30:19 +00:00
Owner - > SetSpecialOwner ( ) ; // indicates if custom dude had life leech.
# endif
break ;
default :
if ( ! ( pSprite - > flags & kHitagRespawn ) )
actor - > SetOwner ( source ) ;
break ;
}
2020-12-03 17:00:07 +00:00
trTriggerSprite ( actor , kCmdOff ) ;
2020-12-02 23:30:19 +00:00
switch ( pSprite - > type )
{
case kThingObjectGib :
case kThingObjectExplode :
case kThingBloodBits :
case kThingBloodChunks :
case kThingZombieHead :
if ( damageType = = 3 & & pSourcePlayer & & PlayClock > pSourcePlayer - > laughCount & & Chance ( 0x4000 ) )
{
2021-11-28 09:24:42 +00:00
sfxPlay3DSound ( pSourcePlayer - > actor , gPlayerGibThingComments [ Random ( 10 ) ] , 0 , 2 ) ;
2020-12-02 23:30:19 +00:00
pSourcePlayer - > laughCount = PlayClock + 3600 ;
}
break ;
case kTrapMachinegun :
2021-09-04 21:27:21 +00:00
seqSpawn ( 28 , actor , - 1 ) ;
2020-12-02 23:30:19 +00:00
break ;
case kThingFluorescent :
2021-09-04 21:27:21 +00:00
seqSpawn ( 12 , actor , - 1 ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_6 , nullptr , nullptr ) ;
2020-12-02 23:30:19 +00:00
break ;
case kThingSpiderWeb :
2021-09-04 21:27:21 +00:00
seqSpawn ( 15 , actor , - 1 ) ;
2020-12-02 23:30:19 +00:00
break ;
case kThingMetalGrate :
2021-09-04 21:27:21 +00:00
seqSpawn ( 21 , actor , - 1 ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_4 , nullptr , nullptr ) ;
2020-12-02 23:30:19 +00:00
break ;
case kThingFlammableTree :
switch ( pXSprite - > data1 )
{
case - 1 :
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_14 , nullptr , nullptr ) ;
2021-11-23 23:38:07 +00:00
sfxPlay3DSound ( pSprite - > x , pSprite - > y , pSprite - > z , 312 , pSprite - > sector ( ) ) ;
2020-12-02 23:30:19 +00:00
actPostSprite ( actor , kStatFree ) ;
break ;
case 0 :
seqSpawn ( 25 , actor , nTreeToGibClient ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 351 , - 1 , 0 ) ;
2020-12-02 23:30:19 +00:00
break ;
case 1 :
2021-09-04 21:27:21 +00:00
seqSpawn ( 26 , actor , nTreeToGibClient ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 351 , - 1 , 0 ) ;
2020-12-02 23:30:19 +00:00
break ;
}
break ;
}
}
return damage ;
2019-09-19 22:42:45 +00:00
}
2020-12-02 23:30:19 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int actDamageSprite ( DBloodActor * source , DBloodActor * actor , DAMAGE_TYPE damageType , int damage )
2020-12-02 19:55:08 +00:00
{
2020-12-02 23:30:19 +00:00
auto pSprite = & actor - > s ( ) ;
if ( pSprite - > flags & 32 | | ! actor - > hasX ( ) )
return 0 ;
XSPRITE * pXSprite = & actor - > x ( ) ;
if ( ( pXSprite - > health = = 0 & & pSprite - > statnum ! = kStatDude ) | | pXSprite - > locked )
return 0 ;
if ( source = = nullptr ) source = actor ;
2020-12-03 17:00:07 +00:00
PLAYER * pSourcePlayer = nullptr ;
2021-12-21 22:18:23 +00:00
if ( source - > IsPlayerActor ( ) ) pSourcePlayer = & gPlayer [ source - > spr . type - kDudePlayer1 ] ;
2020-12-02 23:30:19 +00:00
if ( ! gGameOptions . bFriendlyFire & & IsTargetTeammate ( pSourcePlayer , pSprite ) ) return 0 ;
switch ( pSprite - > statnum )
{
case kStatDude :
damage = actDamageDude ( source , actor , damage , damageType ) ;
break ;
case kStatThing :
damage = actDamageThing ( source , actor , damage , damageType , pSourcePlayer ) ;
break ;
}
return damage > > 4 ;
2020-12-02 19:55:08 +00:00
}
2020-12-02 23:30:19 +00:00
//---------------------------------------------------------------------------
//
2020-12-03 17:00:07 +00:00
// this was condensed to the parts actually in use.
2020-12-02 23:30:19 +00:00
//
//---------------------------------------------------------------------------
2021-11-25 22:28:28 +00:00
void actHitcodeToData ( int a1 , HitInfo * pHitInfo , DBloodActor * * pActor , walltype * * ppWall )
2019-09-19 22:42:45 +00:00
{
2020-12-03 17:00:07 +00:00
assert ( pHitInfo ! = nullptr ) ;
2021-05-05 14:43:42 +00:00
DBloodActor * actor = nullptr ;
2020-12-03 17:00:07 +00:00
walltype * pWall = nullptr ;
switch ( a1 )
{
case 3 :
case 5 :
2021-11-25 22:28:28 +00:00
actor = pHitInfo - > actor ( ) ;
2020-12-03 17:00:07 +00:00
break ;
case 0 :
case 4 :
2021-11-23 16:00:00 +00:00
pWall = pHitInfo - > hitWall ;
2020-12-03 17:00:07 +00:00
break ;
default :
break ;
}
2021-05-05 14:43:42 +00:00
if ( pActor ) * pActor = actor ;
if ( ppWall ) * ppWall = pWall ;
2019-09-19 22:42:45 +00:00
}
2020-12-03 17:00:07 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void actImpactMissile ( DBloodActor * missileActor , int hitCode )
2019-09-19 22:42:45 +00:00
{
2020-12-03 17:00:07 +00:00
auto pMissile = & missileActor - > s ( ) ;
XSPRITE * pXMissile = & missileActor - > x ( ) ;
auto missileOwner = missileActor - > GetOwner ( ) ;
2019-10-11 21:59:39 +00:00
2020-12-03 17:00:07 +00:00
DBloodActor * actorHit = nullptr ;
walltype * pWallHit = nullptr ;
2019-09-21 11:02:17 +00:00
2020-12-03 17:00:07 +00:00
actHitcodeToData ( hitCode , & gHitInfo , & actorHit , & pWallHit ) ;
spritetype * pSpriteHit = actorHit ? & actorHit - > s ( ) : nullptr ;
XSPRITE * pXSpriteHit = actorHit & & actorHit - > hasX ( ) ? & actorHit - > x ( ) : nullptr ;
const THINGINFO * pThingInfo = nullptr ;
DUDEINFO * pDudeInfo = nullptr ;
if ( hitCode = = 3 & & pSpriteHit )
{
switch ( pSpriteHit - > statnum )
{
case kStatThing :
pThingInfo = & thingInfo [ pSpriteHit - > type - kThingBase ] ;
break ;
case kStatDude :
pDudeInfo = getDudeInfo ( pSpriteHit - > type ) ;
break ;
}
}
switch ( pMissile - > type )
{
case kMissileLifeLeechRegular :
if ( hitCode = = 3 & & pSpriteHit & & ( pThingInfo | | pDudeInfo ) )
{
DAMAGE_TYPE rand1 = ( DAMAGE_TYPE ) Random ( 7 ) ;
int rand2 = ( 7 + Random ( 7 ) ) < < 4 ;
int nDamage = actDamageSprite ( missileOwner , actorHit , rand1 , rand2 ) ;
2021-06-16 19:13:04 +00:00
if ( ( pThingInfo & & pThingInfo - > dmgControl [ kDamageBurn ] ! = 0 ) | | ( pDudeInfo & & pDudeInfo - > damageVal [ kDamageBurn ] ! = 0 ) )
2020-12-03 17:00:07 +00:00
actBurnSprite ( missileActor - > GetOwner ( ) , actorHit , 360 ) ;
// by NoOne: make Life Leech heal user, just like it was in 1.0x versions
2021-08-21 10:16:48 +00:00
if ( gGameOptions . weaponsV10x & & ! VanillaMode ( ) & & pDudeInfo ! = nullptr )
2020-12-03 17:00:07 +00:00
{
if ( missileOwner - > IsDudeActor ( ) & & missileOwner - > hasX ( ) & & missileOwner - > x ( ) . health ! = 0 )
2021-12-21 22:18:23 +00:00
actHealDude ( missileOwner , nDamage > > 2 , getDudeInfo ( missileOwner - > spr . type ) - > startHealth ) ;
2020-12-03 17:00:07 +00:00
}
}
2021-09-05 07:59:10 +00:00
if ( missileActor - > hasX ( ) )
2020-12-03 17:00:07 +00:00
{
actPostSprite ( missileActor , kStatDecoration ) ;
2021-11-28 09:24:42 +00:00
if ( pMissile - > ang = = 1024 ) sfxPlay3DSound ( missileActor , 307 , - 1 , 0 ) ;
2020-12-03 17:00:07 +00:00
pMissile - > type = kSpriteDecoration ;
seqSpawn ( 9 , missileActor , - 1 ) ;
}
else
{
2021-08-28 11:59:29 +00:00
actPostSprite ( missileActor , kStatFree ) ;
2020-12-03 17:00:07 +00:00
}
break ;
case kMissileTeslaAlt :
2021-09-04 22:10:28 +00:00
teslaHit ( missileActor , hitCode ) ;
2020-12-03 17:00:07 +00:00
switch ( hitCode )
{
case 0 :
case 4 :
if ( pWallHit )
{
2021-11-23 23:41:19 +00:00
auto pFX = gFX . fxSpawnActor ( FX_52 , pMissile - > sector ( ) , pMissile - > x , pMissile - > y , pMissile - > z , 0 ) ;
2021-12-21 22:18:23 +00:00
if ( pFX ) pFX - > spr . ang = ( GetWallAngle ( pWallHit ) + 512 ) & 2047 ;
2020-12-03 17:00:07 +00:00
}
break ;
}
2021-08-29 20:22:16 +00:00
GibSprite ( missileActor , GIBTYPE_24 , NULL , NULL ) ;
2020-12-03 17:00:07 +00:00
actPostSprite ( missileActor , kStatFree ) ;
break ;
case kMissilePukeGreen :
seqKill ( missileActor ) ;
if ( hitCode = = 3 & & pSpriteHit & & ( pThingInfo | | pDudeInfo ) )
{
int nDamage = ( 15 + Random ( 7 ) ) < < 4 ;
2021-09-16 19:10:23 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageBullet , nDamage ) ;
2020-12-03 17:00:07 +00:00
}
actPostSprite ( missileActor , kStatFree ) ;
break ;
case kMissileArcGargoyle :
2021-11-28 09:24:42 +00:00
sfxKill3DSound ( missileActor , - 1 , - 1 ) ;
2021-11-23 23:38:07 +00:00
sfxPlay3DSound ( pMissile - > x , pMissile - > y , pMissile - > z , 306 , pMissile - > sector ( ) ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( missileActor , GIBTYPE_6 , NULL , NULL ) ;
2020-12-03 17:00:07 +00:00
if ( hitCode = = 3 & & pSpriteHit & & ( pThingInfo | | pDudeInfo ) )
{
int nDamage = ( 25 + Random ( 20 ) ) < < 4 ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageSpirit , nDamage ) ;
2020-12-03 17:00:07 +00:00
}
actPostSprite ( missileActor , kStatFree ) ;
break ;
case kMissileLifeLeechAltNormal :
case kMissileLifeLeechAltSmall :
2021-11-28 09:24:42 +00:00
sfxKill3DSound ( missileActor , - 1 , - 1 ) ;
2021-11-23 23:38:07 +00:00
sfxPlay3DSound ( pMissile - > x , pMissile - > y , pMissile - > z , 306 , pMissile - > sector ( ) ) ;
2020-12-03 17:00:07 +00:00
if ( hitCode = = 3 & & pSpriteHit & & ( pThingInfo | | pDudeInfo ) )
{
int nDmgMul = ( pMissile - > type = = kMissileLifeLeechAltSmall ) ? 6 : 3 ;
int nDamage = ( nDmgMul + Random ( nDmgMul ) ) < < 4 ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageSpirit , nDamage ) ;
2020-12-03 17:00:07 +00:00
}
actPostSprite ( missileActor , kStatFree ) ;
break ;
case kMissileFireball :
2021-08-22 07:49:02 +00:00
case kMissileFireballNapalm :
2020-12-03 17:00:07 +00:00
if ( hitCode = = 3 & & pSpriteHit & & ( pThingInfo | | pDudeInfo ) )
{
if ( pThingInfo & & pSpriteHit - > type = = kThingTNTBarrel & & actorHit - > x ( ) . burnTime = = 0 )
2021-08-27 07:44:47 +00:00
evPostActor ( actorHit , 0 , kCallbackFXFlameLick ) ;
2020-12-03 17:00:07 +00:00
int nDamage = ( 50 + Random ( 50 ) ) < < 4 ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageBullet , nDamage ) ;
2020-12-03 17:00:07 +00:00
}
2020-12-05 11:17:28 +00:00
actExplodeSprite ( missileActor ) ;
2020-12-03 17:00:07 +00:00
break ;
case kMissileFlareAlt :
2021-11-28 09:24:42 +00:00
sfxKill3DSound ( missileActor , - 1 , - 1 ) ;
2020-12-05 11:17:28 +00:00
actExplodeSprite ( missileActor ) ;
2020-12-03 17:00:07 +00:00
break ;
case kMissileFlareRegular :
2021-11-28 09:24:42 +00:00
sfxKill3DSound ( missileActor , - 1 , - 1 ) ;
2020-12-03 17:00:07 +00:00
if ( ( hitCode = = 3 & & pSpriteHit ) & & ( pThingInfo | | pDudeInfo ) )
{
2021-06-16 19:13:04 +00:00
if ( ( pThingInfo & & pThingInfo - > dmgControl [ kDamageBurn ] ! = 0 ) | | ( pDudeInfo & & pDudeInfo - > damageVal [ kDamageBurn ] ! = 0 ) )
2020-12-03 17:00:07 +00:00
{
if ( pThingInfo & & pSpriteHit - > type = = kThingTNTBarrel & & actorHit - > x ( ) . burnTime = = 0 )
2021-08-27 07:44:47 +00:00
evPostActor ( actorHit , 0 , kCallbackFXFlameLick ) ;
2020-12-03 17:00:07 +00:00
actBurnSprite ( missileOwner , actorHit , 480 ) ;
2021-11-23 23:49:29 +00:00
actRadiusDamage ( missileOwner , pMissile - > x , pMissile - > y , pMissile - > z , pMissile - > sector ( ) , 16 , 20 , 10 , kDamageBullet , 6 , 480 ) ;
2020-12-03 17:00:07 +00:00
// by NoOne: allow additional bullet damage for Flare Gun
2021-08-21 10:16:48 +00:00
if ( gGameOptions . weaponsV10x & & ! VanillaMode ( ) )
2020-12-03 17:00:07 +00:00
{
int nDamage = ( 20 + Random ( 10 ) ) < < 4 ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageBullet , nDamage ) ;
2020-12-03 17:00:07 +00:00
}
}
else
{
int nDamage = ( 20 + Random ( 10 ) ) < < 4 ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageBullet , nDamage ) ;
2020-12-03 17:00:07 +00:00
}
if ( surfType [ pSpriteHit - > picnum ] = = kSurfFlesh )
{
pMissile - > picnum = 2123 ;
missileActor - > SetTarget ( actorHit ) ;
pXMissile - > targetZ = pMissile - > z - pSpriteHit - > z ;
pXMissile - > goalAng = getangle ( pMissile - > x - pSpriteHit - > x , pMissile - > y - pSpriteHit - > y ) - pSpriteHit - > ang ;
pXMissile - > state = 1 ;
2021-08-28 11:59:29 +00:00
actPostSprite ( missileActor , kStatFlare ) ;
2021-12-18 15:09:58 +00:00
pMissile - > cstat & = ~ CSTAT_SPRITE_BLOCK_ALL ;
2020-12-03 17:00:07 +00:00
break ;
}
}
2021-08-29 20:22:16 +00:00
GibSprite ( missileActor , GIBTYPE_17 , NULL , NULL ) ;
2020-12-03 17:00:07 +00:00
actPostSprite ( missileActor , kStatFree ) ;
break ;
case kMissileFlameSpray :
case kMissileFlameHound :
if ( hitCode = = 3 & & actorHit & & actorHit - > hasX ( ) )
{
if ( ( pSpriteHit - > statnum = = kStatThing | | pSpriteHit - > statnum = = kStatDude ) & & pXSpriteHit - > burnTime = = 0 )
2021-08-27 07:44:47 +00:00
evPostActor ( actorHit , 0 , kCallbackFXFlameLick ) ;
2020-12-03 17:00:07 +00:00
actBurnSprite ( missileOwner , actorHit , ( 4 + gGameOptions . nDifficulty ) < < 2 ) ;
2021-08-19 12:28:00 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageBurn , 8 ) ;
2020-12-03 17:00:07 +00:00
}
break ;
case kMissileFireballCerberus :
2020-12-05 11:17:28 +00:00
actExplodeSprite ( missileActor ) ;
2020-12-03 17:00:07 +00:00
if ( hitCode = = 3 & & actorHit & & actorHit - > hasX ( ) )
{
if ( ( pSpriteHit - > statnum = = kStatThing | | pSpriteHit - > statnum = = kStatDude ) & & pXSpriteHit - > burnTime = = 0 )
2021-08-27 07:44:47 +00:00
evPostActor ( actorHit , 0 , kCallbackFXFlameLick ) ;
2020-12-03 17:00:07 +00:00
actBurnSprite ( missileOwner , actorHit , ( 4 + gGameOptions . nDifficulty ) < < 2 ) ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageBurn , 8 ) ;
2020-12-03 17:00:07 +00:00
int nDamage = ( 25 + Random ( 10 ) ) < < 4 ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageBullet , nDamage ) ;
2020-12-03 17:00:07 +00:00
}
2020-12-05 11:17:28 +00:00
actExplodeSprite ( missileActor ) ;
2020-12-03 17:00:07 +00:00
break ;
case kMissileFireballTchernobog :
2020-12-05 11:17:28 +00:00
actExplodeSprite ( missileActor ) ;
2020-12-03 17:00:07 +00:00
if ( hitCode = = 3 & & actorHit & & actorHit - > hasX ( ) )
{
if ( ( pSpriteHit - > statnum = = kStatThing | | pSpriteHit - > statnum = = kStatDude ) & & pXSpriteHit - > burnTime = = 0 )
2021-08-27 07:44:47 +00:00
evPostActor ( actorHit , 0 , kCallbackFXFlameLick ) ;
2020-12-03 17:00:07 +00:00
actBurnSprite ( missileOwner , actorHit , 32 ) ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageSpirit , 12 ) ;
2020-12-03 17:00:07 +00:00
int nDamage = ( 25 + Random ( 10 ) ) < < 4 ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageBullet , nDamage ) ;
2020-12-03 17:00:07 +00:00
}
2020-12-05 11:17:28 +00:00
actExplodeSprite ( missileActor ) ;
2020-12-03 17:00:07 +00:00
break ;
case kMissileEctoSkull :
2021-11-28 09:24:42 +00:00
sfxKill3DSound ( missileActor , - 1 , - 1 ) ;
2021-11-23 23:38:07 +00:00
sfxPlay3DSound ( pMissile - > x , pMissile - > y , pMissile - > z , 522 , pMissile - > sector ( ) ) ;
2021-08-28 11:59:29 +00:00
actPostSprite ( missileActor , kStatDebris ) ;
2021-09-04 21:27:21 +00:00
seqSpawn ( 20 , missileActor , - 1 ) ;
2020-12-03 17:00:07 +00:00
if ( hitCode = = 3 & & actorHit & & actorHit - > hasX ( ) )
{
if ( pSpriteHit - > statnum = = kStatDude )
{
int nDamage = ( 25 + Random ( 10 ) ) < < 4 ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageSpirit , nDamage ) ;
2020-12-03 17:00:07 +00:00
}
}
break ;
case kMissileButcherKnife :
actPostSprite ( missileActor , kStatDebris ) ;
2021-12-18 18:19:28 +00:00
pMissile - > cstat & = ~ CSTAT_SPRITE_ALIGNMENT_WALL ;
2020-12-03 17:00:07 +00:00
pMissile - > type = kSpriteDecoration ;
2021-09-04 21:27:21 +00:00
seqSpawn ( 20 , missileActor , - 1 ) ;
2020-12-03 17:00:07 +00:00
if ( hitCode = = 3 & & actorHit & & actorHit - > hasX ( ) )
{
if ( pSpriteHit - > statnum = = kStatDude )
{
int nDamage = ( 10 + Random ( 10 ) ) < < 4 ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageSpirit , nDamage ) ;
2021-12-21 22:18:23 +00:00
int nType = missileOwner - > spr . type - kDudeBase ;
2020-12-03 17:00:07 +00:00
if ( missileOwner - > x ( ) . health > 0 )
actHealDude ( missileOwner , 10 , getDudeInfo ( nType + kDudeBase ) - > startHealth ) ;
}
}
break ;
case kMissileTeslaRegular :
2021-11-28 09:24:42 +00:00
sfxKill3DSound ( missileActor , - 1 , - 1 ) ;
2021-11-23 23:38:07 +00:00
sfxPlay3DSound ( pMissile - > x , pMissile - > y , pMissile - > z , 518 , pMissile - > sector ( ) ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( missileActor , ( hitCode = = 2 ) ? GIBTYPE_23 : GIBTYPE_22 , NULL , NULL ) ;
2021-08-27 07:44:47 +00:00
evKillActor ( missileActor ) ;
2020-12-03 17:00:07 +00:00
seqKill ( missileActor ) ;
actPostSprite ( missileActor , kStatFree ) ;
if ( hitCode = = 3 & & actorHit )
{
int nDamage = ( 15 + Random ( 10 ) ) < < 4 ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageTesla , nDamage ) ;
2020-12-03 17:00:07 +00:00
}
break ;
default :
seqKill ( missileActor ) ;
actPostSprite ( missileActor , kStatFree ) ;
if ( hitCode = = 3 & & actorHit )
{
int nDamage = ( 10 + Random ( 10 ) ) < < 4 ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( missileOwner , actorHit , kDamageFall , nDamage ) ;
2020-12-03 17:00:07 +00:00
}
break ;
}
# ifdef NOONE_EXTENSIONS
if ( gModernMap & & pXSpriteHit & & pXSpriteHit - > state ! = pXSpriteHit - > restState & & pXSpriteHit - > Impact )
trTriggerSprite ( actorHit , kCmdSpriteImpact ) ;
# endif
2021-12-18 15:09:58 +00:00
pMissile - > cstat & = ~ CSTAT_SPRITE_BLOCK_ALL ;
2019-09-19 22:42:45 +00:00
}
2020-12-03 17:38:30 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void actKickObject ( DBloodActor * kicker , DBloodActor * kicked )
2019-09-19 22:42:45 +00:00
{
2021-09-04 10:52:02 +00:00
int nSpeed = ClipLow ( approxDist ( kicker - > xvel , kicker - > yvel ) * 2 , 0xaaaaa ) ;
2021-12-21 22:18:23 +00:00
kicked - > xvel = MulScale ( nSpeed , Cos ( kicker - > spr . ang + Random2 ( 85 ) ) , 30 ) ;
kicked - > yvel = MulScale ( nSpeed , Sin ( kicker - > spr . ang + Random2 ( 85 ) ) , 30 ) ;
2021-09-04 10:52:02 +00:00
kicked - > zvel = MulScale ( nSpeed , - 0x2000 , 14 ) ;
2021-12-21 22:18:23 +00:00
kicked - > spr . flags = 7 ;
2019-09-19 22:42:45 +00:00
}
2020-12-03 17:38:30 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-11-19 17:08:05 +00:00
static void actTouchFloor ( DBloodActor * actor , sectortype * pSector )
2019-09-19 22:42:45 +00:00
{
2021-11-19 17:08:05 +00:00
XSECTOR * pXSector = pSector - > hasX ( ) ? & pSector - > xs ( ) : nullptr ;
2019-09-19 22:42:45 +00:00
2020-12-06 20:56:09 +00:00
bool doDamage = ( pXSector & & ( pSector - > type = = kSectorDamage | | pXSector - > damageType > 0 ) ) ;
// don't allow damage for damage sectors if they are not enabled
2021-08-25 06:46:31 +00:00
# ifdef NOONE_EXTENSIONS
2020-12-06 20:56:09 +00:00
if ( gModernMap & & doDamage & & pSector - > type = = kSectorDamage & & ! pXSector - > state )
doDamage = false ;
2021-08-25 06:46:31 +00:00
# endif
2020-12-06 20:56:09 +00:00
if ( doDamage ) {
2020-12-03 17:38:30 +00:00
DAMAGE_TYPE nDamageType ;
2021-06-16 19:13:04 +00:00
if ( pSector - > type = = kSectorDamage ) nDamageType = ( DAMAGE_TYPE ) ClipRange ( pXSector - > damageType , kDamageFall , kDamageTesla ) ;
else nDamageType = ( DAMAGE_TYPE ) ClipRange ( pXSector - > damageType - 1 , kDamageFall , kDamageTesla ) ;
2019-10-20 14:50:47 +00:00
2020-12-03 17:38:30 +00:00
int nDamage ;
if ( pXSector - > data ) nDamage = ClipRange ( pXSector - > data , 0 , 1000 ) ;
else nDamage = 1000 ;
2019-10-20 14:50:47 +00:00
2020-12-03 17:38:30 +00:00
actDamageSprite ( actor , actor , nDamageType , scale ( 4 , nDamage , 120 ) < < 4 ) ;
}
2021-11-19 17:08:05 +00:00
if ( tileGetSurfType ( pSector - > floorpicnum ) = = kSurfLava )
2020-12-03 17:38:30 +00:00
{
2021-06-16 19:13:04 +00:00
actDamageSprite ( actor , actor , kDamageBurn , 16 ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 352 , 5 , 2 ) ;
2020-12-03 17:38:30 +00:00
}
2019-09-19 22:42:45 +00:00
}
2020-12-03 17:38:30 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-12-03 19:30:30 +00:00
static void checkCeilHit ( DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2020-12-03 17:38:30 +00:00
auto pSprite = & actor - > s ( ) ;
2020-12-03 19:30:30 +00:00
auto pXSprite = actor - > hasX ( ) ? & actor - > x ( ) : nullptr ;
2020-12-03 17:38:30 +00:00
2021-12-05 19:55:19 +00:00
auto & coll = actor - > hit . ceilhit ;
2020-12-03 19:30:30 +00:00
switch ( coll . type )
{
case kHitWall :
break ;
case kHitSprite :
2021-12-05 19:55:19 +00:00
auto actor2 = coll . actor ( ) ;
if ( actor2 & & actor2 - > hasX ( ) )
2020-12-03 19:30:30 +00:00
{
spritetype * pSprite2 = & actor2 - > s ( ) ;
XSPRITE * pXSprite2 = & actor2 - > x ( ) ;
2021-09-04 10:52:02 +00:00
if ( ( pSprite2 - > statnum = = kStatThing | | pSprite2 - > statnum = = kStatDude ) & & ( actor - > xvel ! = 0 | | actor - > yvel ! = 0 | | actor - > zvel ! = 0 ) )
2020-12-03 19:30:30 +00:00
{
if ( pSprite2 - > statnum = = kStatThing )
{
int nType = pSprite2 - > type - kThingBase ;
const THINGINFO * pThingInfo = & thingInfo [ nType ] ;
if ( pThingInfo - > flags & 1 ) pSprite2 - > flags | = 1 ;
if ( pThingInfo - > flags & 2 ) pSprite2 - > flags | = 4 ;
// Inlined ?
2021-09-04 10:52:02 +00:00
actor2 - > xvel + = MulScale ( 4 , pSprite2 - > x - pSprite - > x , 2 ) ;
actor2 - > yvel + = MulScale ( 4 , pSprite2 - > y - pSprite - > y , 2 ) ;
2020-12-03 19:30:30 +00:00
}
else
{
pSprite2 - > flags | = 5 ;
2021-09-04 10:52:02 +00:00
actor2 - > xvel + = MulScale ( 4 , pSprite2 - > x - pSprite - > x , 2 ) ;
actor2 - > yvel + = MulScale ( 4 , pSprite2 - > y - pSprite - > y , 2 ) ;
2020-12-03 19:30:30 +00:00
# ifdef NOONE_EXTENSIONS
// add size shroom abilities
2021-08-29 11:44:04 +00:00
if ( ( actor - > IsPlayerActor ( ) & & isShrinked ( actor ) ) | | ( actor2 - > IsPlayerActor ( ) & & isGrown ( actor2 ) ) ) {
2020-12-03 19:30:30 +00:00
int mass1 = getDudeInfo ( pSprite2 - > type ) - > mass ;
int mass2 = getDudeInfo ( pSprite - > type ) - > mass ;
switch ( pSprite - > type )
{
case kDudeModernCustom :
case kDudeModernCustomBurning :
2021-08-27 17:12:22 +00:00
mass2 = getSpriteMassBySize ( actor ) ;
2020-12-03 19:30:30 +00:00
break ;
}
if ( mass1 > mass2 )
{
int dmg = abs ( ( mass1 - mass2 ) * ( pSprite2 - > clipdist - pSprite - > clipdist ) ) ;
if ( actor2 - > IsDudeActor ( ) )
{
2021-09-16 19:10:23 +00:00
if ( dmg > 0 ) actDamageSprite ( actor2 , actor , ( Chance ( 0x2000 ) ) ? kDamageFall : ( Chance ( 0x4000 ) ) ? kDamageExplode : kDamageBullet , dmg ) ;
2020-12-03 19:30:30 +00:00
if ( Chance ( 0x0200 ) ) actKickObject ( actor2 , actor ) ;
}
}
}
# endif
if ( ! actor - > IsPlayerActor ( ) | | gPlayer [ pSprite - > type - kDudePlayer1 ] . godMode = = 0 )
{
switch ( pSprite2 - > type )
{
case kDudeTchernobog :
2021-06-16 19:13:04 +00:00
actDamageSprite ( actor2 , actor , kDamageExplode , pXSprite - > health < < 2 ) ;
2020-12-03 19:30:30 +00:00
break ;
# ifdef NOONE_EXTENSIONS
case kDudeModernCustom :
case kDudeModernCustomBurning :
int dmg = 0 ;
2021-08-27 17:12:22 +00:00
if ( ! actor - > IsDudeActor ( ) | | ( dmg = ClipLow ( ( getSpriteMassBySize ( actor2 ) - getSpriteMassBySize ( actor ) ) > > 1 , 0 ) ) = = 0 )
2020-12-03 19:30:30 +00:00
break ;
if ( ! actor - > IsPlayerActor ( ) )
{
2021-06-16 19:13:04 +00:00
actDamageSprite ( actor2 , actor , kDamageFall , dmg ) ;
2020-12-03 19:30:30 +00:00
if ( pXSprite & & ! actor - > isActive ( ) ) aiActivateDude ( actor ) ;
}
2021-06-16 19:13:04 +00:00
else if ( powerupCheck ( & gPlayer [ pSprite - > type - kDudePlayer1 ] , kPwUpJumpBoots ) > 0 ) actDamageSprite ( actor2 , actor , kDamageExplode , dmg ) ;
else actDamageSprite ( actor2 , actor , kDamageFall , dmg ) ;
2020-12-03 19:30:30 +00:00
break ;
# endif
}
}
}
}
if ( pSprite2 - > type = = kTrapSawCircular )
{
2021-06-16 19:13:04 +00:00
if ( ! pXSprite2 - > state ) actDamageSprite ( actor , actor , kDamageBullet , 1 ) ;
2020-12-03 19:30:30 +00:00
else {
pXSprite2 - > data1 = 1 ;
pXSprite2 - > data2 = ClipHigh ( pXSprite2 - > data2 + 8 , 600 ) ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( actor , actor , kDamageBullet , 16 ) ;
2020-12-03 19:30:30 +00:00
}
}
}
break ;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void checkHit ( DBloodActor * actor )
{
auto pSprite = & actor - > s ( ) ;
auto pXSprite = actor - > hasX ( ) ? & actor - > x ( ) : nullptr ;
2021-12-11 01:59:46 +00:00
const auto & coll = actor - > hit . hit ;
2020-12-03 19:30:30 +00:00
switch ( coll . type )
{
case kHitWall :
break ;
case kHitSprite :
2021-11-26 13:03:21 +00:00
if ( coll . actor ( ) - > hasX ( ) )
2020-12-03 19:30:30 +00:00
{
2021-11-26 13:03:21 +00:00
auto actor2 = coll . actor ( ) ;
2020-12-03 19:30:30 +00:00
spritetype * pSprite2 = & actor2 - > s ( ) ;
# ifdef NOONE_EXTENSIONS
// add size shroom abilities
2021-08-29 11:44:04 +00:00
if ( ( actor2 - > IsPlayerActor ( ) & & isShrinked ( actor2 ) ) | | ( actor - > IsPlayerActor ( ) & & isGrown ( actor ) ) )
2020-12-03 19:30:30 +00:00
{
2021-09-04 10:52:02 +00:00
if ( actor - > xvel ! = 0 & & actor2 - > IsDudeActor ( ) )
2020-12-03 19:30:30 +00:00
{
int mass1 = getDudeInfo ( pSprite - > type ) - > mass ;
int mass2 = getDudeInfo ( pSprite2 - > type ) - > mass ;
switch ( pSprite2 - > type )
{
case kDudeModernCustom :
case kDudeModernCustomBurning :
2021-08-27 17:12:22 +00:00
mass2 = getSpriteMassBySize ( actor2 ) ;
2020-12-03 19:30:30 +00:00
break ;
}
if ( mass1 > mass2 )
{
actKickObject ( actor , actor2 ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 357 , - 1 , 1 ) ;
2021-09-04 10:52:02 +00:00
int dmg = ( mass1 - mass2 ) + abs ( FixedToInt ( actor - > xvel ) ) ;
2021-06-16 19:13:04 +00:00
if ( dmg > 0 ) actDamageSprite ( actor , actor2 , ( Chance ( 0x2000 ) ) ? kDamageFall : kDamageBullet , dmg ) ;
2020-12-03 19:30:30 +00:00
}
}
}
# endif
switch ( pSprite2 - > type )
{
case kThingKickablePail :
actKickObject ( actor , actor2 ) ;
break ;
case kThingZombieHead :
2021-11-23 23:38:07 +00:00
sfxPlay3DSound ( pSprite - > x , pSprite - > y , pSprite - > z , 357 , pSprite - > sector ( ) ) ;
2020-12-03 19:30:30 +00:00
actKickObject ( actor , actor2 ) ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( nullptr , actor2 , kDamageFall , 80 ) ;
2020-12-03 19:30:30 +00:00
break ;
case kDudeBurningInnocent :
case kDudeBurningCultist :
case kDudeBurningZombieAxe :
case kDudeBurningZombieButcher :
// This does not make sense
pXSprite - > burnTime = ClipLow ( pXSprite - > burnTime - 4 , 0 ) ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( actor - > GetBurnSource ( ) , actor , kDamageBurn , 8 ) ;
2020-12-03 19:30:30 +00:00
break ;
}
}
break ;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void checkFloorHit ( DBloodActor * actor )
{
auto pSprite = & actor - > s ( ) ;
2021-12-11 01:59:46 +00:00
const auto & coll = actor - > hit . florhit ;
2020-12-03 19:30:30 +00:00
switch ( coll . type )
{
case kHitWall :
break ;
case kHitSector :
2021-11-26 13:03:21 +00:00
actTouchFloor ( actor , coll . hitSector ) ;
2020-12-03 19:30:30 +00:00
break ;
case kHitSprite :
2021-11-26 13:03:21 +00:00
if ( coll . actor ( ) - > hasX ( ) )
2020-12-03 19:30:30 +00:00
{
2021-11-26 13:03:21 +00:00
auto actor2 = coll . actor ( ) ;
2020-12-03 19:30:30 +00:00
spritetype * pSprite2 = & actor2 - > s ( ) ;
XSPRITE * pXSprite2 = & actor2 - > x ( ) ;
# ifdef NOONE_EXTENSIONS
// add size shroom abilities
2021-08-29 11:44:04 +00:00
if ( ( actor2 - > IsPlayerActor ( ) & & isShrinked ( actor2 ) ) | | ( actor - > IsPlayerActor ( ) & & isGrown ( actor ) ) )
2020-12-03 19:30:30 +00:00
{
int mass1 = getDudeInfo ( pSprite - > type ) - > mass ;
int mass2 = getDudeInfo ( pSprite2 - > type ) - > mass ;
switch ( pSprite2 - > type )
{
case kDudeModernCustom :
case kDudeModernCustomBurning :
2021-08-27 17:12:22 +00:00
mass2 = getSpriteMassBySize ( actor2 ) ;
2020-12-03 19:30:30 +00:00
break ;
}
2021-09-01 19:52:36 +00:00
if ( mass1 > mass2 & & actor2 - > IsDudeActor ( ) )
2020-12-03 19:30:30 +00:00
{
if ( ( IsPlayerSprite ( pSprite2 ) & & Chance ( 0x500 ) ) | | ! IsPlayerSprite ( pSprite2 ) )
actKickObject ( actor , actor2 ) ;
int dmg = ( mass1 - mass2 ) + pSprite - > clipdist ;
2021-06-16 19:13:04 +00:00
if ( dmg > 0 ) actDamageSprite ( actor , actor2 , ( Chance ( 0x2000 ) ) ? kDamageFall : kDamageBullet , dmg ) ;
2020-12-03 19:30:30 +00:00
}
}
# endif
PLAYER * pPlayer = nullptr ;
if ( actor - > IsPlayerActor ( ) ) pPlayer = & gPlayer [ pSprite - > type - kDudePlayer1 ] ;
switch ( pSprite2 - > type )
{
case kThingKickablePail :
if ( pPlayer )
{
if ( pPlayer - > kickPower > PlayClock ) return ;
pPlayer - > kickPower = PlayClock + 60 ;
}
actKickObject ( actor , actor2 ) ;
2021-11-23 23:38:07 +00:00
sfxPlay3DSound ( pSprite - > x , pSprite - > y , pSprite - > z , 357 , pSprite - > sector ( ) ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 374 , 0 , 0 ) ;
2020-12-03 19:30:30 +00:00
break ;
case kThingZombieHead :
if ( pPlayer )
{
if ( pPlayer - > kickPower > PlayClock ) return ;
pPlayer - > kickPower = PlayClock + 60 ;
}
actKickObject ( actor , actor2 ) ;
2021-11-23 23:38:07 +00:00
sfxPlay3DSound ( pSprite - > x , pSprite - > y , pSprite - > z , 357 , pSprite - > sector ( ) ) ;
2021-09-16 19:10:23 +00:00
actDamageSprite ( nullptr , actor2 , kDamageFall , 80 ) ;
2020-12-03 19:30:30 +00:00
break ;
case kTrapSawCircular :
2021-06-16 19:13:04 +00:00
if ( ! pXSprite2 - > state ) actDamageSprite ( actor , actor , kDamageBullet , 1 ) ;
2020-12-03 19:30:30 +00:00
else
{
pXSprite2 - > data1 = 1 ;
pXSprite2 - > data2 = ClipHigh ( pXSprite2 - > data2 + 8 , 600 ) ;
2021-06-16 19:13:04 +00:00
actDamageSprite ( actor , actor , kDamageBullet , 16 ) ;
2020-12-03 19:30:30 +00:00
}
break ;
case kDudeCultistTommy :
case kDudeCultistShotgun :
case kDudeZombieAxeNormal :
case kDudeZombieButcher :
case kDudeZombieAxeBuried :
case kDudeGargoyleFlesh :
case kDudeGargoyleStone :
case kDudePhantasm :
case kDudeHellHound :
case kDudeHand :
case kDudeSpiderBrown :
case kDudeSpiderRed :
case kDudeSpiderBlack :
case kDudeGillBeast :
case kDudeBat :
case kDudeRat :
case kDudePodGreen :
case kDudeTentacleGreen :
case kDudePodFire :
case kDudeTentacleFire :
case kDudePodMother :
case kDudeTentacleMother :
case kDudeCerberusTwoHead :
case kDudeCerberusOneHead :
case kDudeTchernobog :
case kDudePlayer1 :
case kDudePlayer2 :
case kDudePlayer3 :
case kDudePlayer4 :
case kDudePlayer5 :
case kDudePlayer6 :
case kDudePlayer7 :
case kDudePlayer8 :
# ifdef NOONE_EXTENSIONS
2021-08-29 11:44:04 +00:00
if ( pPlayer & & ! isShrinked ( actor ) )
2020-12-03 19:30:30 +00:00
# else
if ( pPlayer )
# endif
2021-06-16 19:13:04 +00:00
actDamageSprite ( actor , actor2 , kDamageBullet , 8 ) ;
2020-12-03 19:30:30 +00:00
break ;
}
}
break ;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void ProcessTouchObjects ( DBloodActor * actor )
{
checkCeilHit ( actor ) ;
checkHit ( actor ) ;
checkFloorHit ( actor ) ;
# ifdef NOONE_EXTENSIONS
// add more trigger statements for Touch flag
if ( gModernMap & & actor - > IsDudeActor ( ) )
{
DBloodActor * actor2 = nullptr ;
2021-12-05 19:55:19 +00:00
for ( auto * coll : { & actor - > hit . hit , & actor - > hit . florhit , & actor - > hit . ceilhit } )
2020-12-03 19:30:30 +00:00
{
2021-09-02 18:23:51 +00:00
if ( coll - > type = = kHitSprite )
2020-12-03 19:30:30 +00:00
{
2021-11-26 13:03:21 +00:00
actor2 = coll - > actor ( ) ;
2020-12-03 19:30:30 +00:00
break ;
}
}
2021-07-18 06:56:49 +00:00
if ( actor2 & & actor2 - > hasX ( ) )
2020-12-03 17:38:30 +00:00
{
2020-12-03 19:30:30 +00:00
XSPRITE * pXHSprite = & actor2 - > x ( ) ;
if ( pXHSprite - > Touch & & ! pXHSprite - > isTriggered & & ( ! pXHSprite - > DudeLockout | | actor - > IsPlayerActor ( ) ) )
trTriggerSprite ( actor2 , kCmdSpriteTouch ) ;
}
// Touch walls
2021-12-11 01:59:46 +00:00
const auto & coll = actor - > hit . hit ;
2021-11-19 00:12:05 +00:00
walltype * pHWall = nullptr ;
2020-12-03 19:30:30 +00:00
if ( coll . type = = kHitWall )
{
2021-11-26 13:03:21 +00:00
pHWall = coll . hitWall ;
2021-11-19 00:12:05 +00:00
if ( pHWall & & pHWall - > hasX ( ) )
2020-12-03 17:38:30 +00:00
{
2021-11-19 00:12:05 +00:00
if ( pHWall - > xw ( ) . triggerTouch & & ! pHWall - > xw ( ) . isTriggered & & ( ! pHWall - > xw ( ) . dudeLockout | | actor - > IsPlayerActor ( ) ) )
trTriggerWall ( pHWall , kCmdWallTouch ) ;
2020-12-03 19:30:30 +00:00
}
}
2019-12-23 20:10:28 +00:00
2020-12-03 19:30:30 +00:00
// enough to reset SpriteHit values
2021-11-19 00:12:05 +00:00
if ( pHWall ! = nullptr | | actor2 ) actor - > xvel + = 5 ;
2020-01-01 20:53:29 +00:00
2020-12-03 19:30:30 +00:00
}
# endif
2019-09-19 22:42:45 +00:00
}
2020-12-03 19:30:30 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-12-03 21:04:07 +00:00
void actAirDrag ( DBloodActor * actor , int a2 )
2019-09-19 22:42:45 +00:00
{
2020-12-03 21:04:07 +00:00
auto pSprite = & actor - > s ( ) ;
int wind_x = 0 ;
int wind_y = 0 ;
2021-11-23 23:38:07 +00:00
assert ( pSprite - > sector ( ) ) ;
2021-11-19 17:08:05 +00:00
sectortype * pSector = pSprite - > sector ( ) ;
if ( pSector - > hasX ( ) )
2021-08-23 17:21:41 +00:00
{
2021-11-19 17:08:05 +00:00
XSECTOR * pXSector = & pSector - > xs ( ) ;
2021-08-23 17:21:41 +00:00
if ( pXSector - > windVel & & ( pXSector - > windAlways | | pXSector - > busy ) )
{
2020-12-03 21:04:07 +00:00
int wind = pXSector - > windVel < < 12 ;
if ( ! pXSector - > windAlways & & pXSector - > busy ) wind = MulScale ( wind , pXSector - > busy , 16 ) ;
wind_x = MulScale ( wind , Cos ( pXSector - > windAng ) , 30 ) ;
wind_y = MulScale ( wind , Sin ( pXSector - > windAng ) , 30 ) ;
2021-08-23 17:21:41 +00:00
}
}
2021-09-04 10:52:02 +00:00
actor - > xvel + = MulScale ( wind_x - actor - > xvel , a2 , 16 ) ;
actor - > yvel + = MulScale ( wind_y - actor - > yvel , a2 , 16 ) ;
actor - > zvel - = MulScale ( actor - > zvel , a2 , 16 ) ;
2019-09-19 22:42:45 +00:00
}
2020-12-03 21:04:07 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-09-02 18:23:51 +00:00
static Collision MoveThing ( DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2020-12-03 21:04:07 +00:00
auto pSprite = & actor - > s ( ) ;
assert ( actor - > hasX ( ) ) ;
2021-08-23 17:21:41 +00:00
assert ( pSprite - > type > = kThingBase & & pSprite - > type < kThingMax ) ;
2020-12-03 21:04:07 +00:00
const THINGINFO * pThingInfo = & thingInfo [ pSprite - > type - kThingBase ] ;
2021-11-23 23:18:14 +00:00
auto pSector = pSprite - > sector ( ) ;
assert ( pSector ) ;
2021-08-23 17:21:41 +00:00
int top , bottom ;
2021-09-02 18:23:51 +00:00
Collision lhit ;
2020-12-03 21:04:07 +00:00
2021-09-02 18:23:51 +00:00
lhit . setNone ( ) ;
2020-12-03 21:04:07 +00:00
GetActorExtents ( actor , & top , & bottom ) ;
2021-08-23 17:21:41 +00:00
const int bakCompat = enginecompatibility_mode ;
2021-09-04 10:52:02 +00:00
if ( actor - > xvel | | actor - > yvel )
2021-08-23 17:21:41 +00:00
{
2021-11-16 17:15:56 +00:00
auto bakCstat = pSprite - > cstat ;
2021-12-18 15:09:58 +00:00
pSprite - > cstat & = ~ CSTAT_SPRITE_BLOCK_ALL ;
2021-08-29 21:10:19 +00:00
if ( ( actor - > GetOwner ( ) ) & & ! cl_bloodvanillaexplosions & & ! VanillaMode ( ) )
2021-08-23 17:21:41 +00:00
enginecompatibility_mode = ENGINECOMPATIBILITY_NONE ; // improved clipmove accuracy
2021-11-26 13:03:21 +00:00
ClipMove ( pSprite - > pos , & pSector , actor - > xvel > > 12 , actor - > yvel > > 12 , pSprite - > clipdist < < 2 , ( pSprite - > z - top ) / 4 , ( bottom - pSprite - > z ) / 4 , CLIPMASK0 , lhit ) ;
actor - > hit . hit = lhit ;
2021-08-23 17:21:41 +00:00
enginecompatibility_mode = bakCompat ; // restore
pSprite - > cstat = bakCstat ;
2021-11-23 23:18:14 +00:00
assert ( pSector ) ;
if ( pSprite - > sector ( ) ! = pSector )
2021-08-23 17:21:41 +00:00
{
2021-11-23 23:18:14 +00:00
assert ( pSector ) ;
ChangeActorSect ( actor , pSector ) ;
2021-08-23 17:21:41 +00:00
}
2020-12-03 21:04:07 +00:00
2021-12-05 19:55:19 +00:00
auto & coll = actor - > hit . hit ;
2020-12-03 21:04:07 +00:00
if ( coll . type = = kHitWall )
{
2021-11-26 13:03:21 +00:00
actWallBounceVector ( & actor - > xvel , & actor - > yvel , coll . hitWall , pThingInfo - > elastic ) ;
2020-12-03 21:04:07 +00:00
switch ( pSprite - > type )
{
2021-08-25 06:46:31 +00:00
case kThingZombieHead :
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 607 , 0 , 0 ) ;
2020-12-03 21:04:07 +00:00
actDamageSprite ( nullptr , actor , kDamageFall , 80 ) ;
2021-08-25 06:46:31 +00:00
break ;
2021-08-23 17:21:41 +00:00
2021-08-25 06:46:31 +00:00
case kThingKickablePail :
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 374 , 0 , 0 ) ;
2021-08-25 06:46:31 +00:00
break ;
2021-08-23 17:21:41 +00:00
}
}
}
else
{
2021-11-23 23:18:14 +00:00
assert ( pSector ) ;
FindSector ( pSprite - > x , pSprite - > y , pSprite - > z , & pSector ) ;
2021-08-23 17:21:41 +00:00
}
2020-12-03 21:04:07 +00:00
2021-09-04 10:52:02 +00:00
pSprite - > z + = actor - > zvel > > 8 ;
2020-12-03 21:04:07 +00:00
2021-09-02 18:23:51 +00:00
int ceilZ , floorZ ;
Collision ceilColl , floorColl ;
2021-09-04 18:19:38 +00:00
GetZRange ( actor , & ceilZ , & ceilColl , & floorZ , & floorColl , pSprite - > clipdist < < 2 , CLIPMASK0 ) ;
2020-12-03 21:04:07 +00:00
GetActorExtents ( actor , & top , & bottom ) ;
2021-08-23 17:21:41 +00:00
if ( ( pSprite - > flags & 2 ) & & bottom < floorZ )
{
pSprite - > z + = 455 ;
2021-09-04 10:52:02 +00:00
actor - > zvel + = 58254 ;
2021-08-23 17:21:41 +00:00
if ( pSprite - > type = = kThingZombieHead )
{
2021-11-23 23:41:19 +00:00
auto * fxActor = gFX . fxSpawnActor ( FX_27 , pSprite - > sector ( ) , pSprite - > x , pSprite - > y , pSprite - > z , 0 ) ;
2020-12-03 21:04:07 +00:00
if ( fxActor )
2021-08-23 17:21:41 +00:00
{
2020-12-03 21:04:07 +00:00
int v34 = ( PlayClock * 3 ) & 2047 ;
int v30 = ( PlayClock * 5 ) & 2047 ;
int vbx = ( PlayClock * 11 ) & 2047 ;
2021-08-23 17:21:41 +00:00
int v2c = 0x44444 ;
int v28 = 0 ;
int v24 = 0 ;
2020-12-03 21:04:07 +00:00
RotateVector ( & v2c , & v28 , vbx ) ;
RotateVector ( & v2c , & v24 , v30 ) ;
RotateVector ( & v28 , & v24 , v34 ) ;
2021-09-04 10:52:02 +00:00
fxActor - > xvel = actor - > xvel + v2c ;
fxActor - > yvel = actor - > yvel + v28 ;
fxActor - > zvel = actor - > zvel + v24 ;
2021-08-23 17:21:41 +00:00
}
}
}
2021-09-04 18:19:38 +00:00
if ( CheckLink ( actor ) ) GetZRange ( actor , & ceilZ , & ceilColl , & floorZ , & floorColl , pSprite - > clipdist < < 2 , CLIPMASK0 ) ;
2020-12-03 21:04:07 +00:00
GetActorExtents ( actor , & top , & bottom ) ;
2021-08-23 17:21:41 +00:00
if ( bottom > = floorZ )
{
2021-11-19 17:08:05 +00:00
actTouchFloor ( actor , pSprite - > sector ( ) ) ;
2021-08-29 17:09:29 +00:00
actor - > hit . florhit = floorColl ;
2020-12-03 21:04:07 +00:00
pSprite - > z + = floorZ - bottom ;
2021-11-20 18:10:02 +00:00
int v20 = actor - > zvel - pSprite - > sector ( ) - > velFloor ;
2021-08-23 17:21:41 +00:00
if ( v20 > 0 )
{
2019-10-20 14:50:47 +00:00
2021-08-23 17:21:41 +00:00
pSprite - > flags | = 4 ;
2021-11-23 23:12:37 +00:00
int vax = actFloorBounceVector ( & actor - > xvel , & actor - > yvel , ( int * ) & v20 , pSprite - > sector ( ) , pThingInfo - > elastic ) ;
2020-12-03 21:04:07 +00:00
int nDamage = MulScale ( vax , vax , 30 ) - pThingInfo - > dmgResist ;
if ( nDamage > 0 ) actDamageSprite ( actor , actor , kDamageFall , nDamage ) ;
2019-10-20 14:50:47 +00:00
2021-09-04 10:52:02 +00:00
actor - > zvel = v20 ;
2021-11-20 18:10:02 +00:00
if ( pSprite - > sector ( ) - > velFloor = = 0 & & abs ( actor - > zvel ) < 0x10000 )
2021-08-23 17:21:41 +00:00
{
2021-09-04 10:52:02 +00:00
actor - > zvel = 0 ;
2021-08-23 17:21:41 +00:00
pSprite - > flags & = ~ 4 ;
}
2020-12-03 21:04:07 +00:00
switch ( pSprite - > type )
{
2021-08-25 06:46:31 +00:00
case kThingNapalmBall :
2021-09-04 10:52:02 +00:00
if ( actor - > zvel = = 0 | | Chance ( 0xA000 ) ) actNapalmMove ( actor ) ;
2021-08-25 06:46:31 +00:00
break ;
2020-12-03 21:04:07 +00:00
2021-08-25 06:46:31 +00:00
case kThingZombieHead :
2021-09-04 10:52:02 +00:00
if ( abs ( actor - > zvel ) > 0x80000 )
2020-12-03 21:04:07 +00:00
{
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 607 , 0 , 0 ) ;
2020-12-03 21:04:07 +00:00
actDamageSprite ( nullptr , actor , kDamageFall , 80 ) ;
2021-08-25 06:46:31 +00:00
}
break ;
2020-12-03 21:04:07 +00:00
2021-08-25 06:46:31 +00:00
case kThingKickablePail :
2021-09-04 10:52:02 +00:00
if ( abs ( actor - > zvel ) > 0x80000 )
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 374 , 0 , 0 ) ;
2021-08-25 06:46:31 +00:00
break ;
2021-08-23 17:21:41 +00:00
}
2019-10-11 21:59:39 +00:00
2021-11-23 23:18:14 +00:00
lhit . setSector ( pSector ) ;
2021-08-23 17:21:41 +00:00
}
2021-09-04 10:52:02 +00:00
else if ( actor - > zvel = = 0 )
2019-10-20 14:50:47 +00:00
2021-08-23 17:21:41 +00:00
pSprite - > flags & = ~ 4 ;
}
else
{
2021-11-26 13:03:21 +00:00
actor - > hit . florhit . setNone ( ) ;
2019-10-20 14:50:47 +00:00
2020-12-03 21:04:07 +00:00
if ( pSprite - > flags & 2 )
2021-08-23 17:21:41 +00:00
pSprite - > flags | = 4 ;
}
2020-12-03 21:04:07 +00:00
2021-08-23 17:21:41 +00:00
if ( top < = ceilZ )
{
2021-08-29 17:09:29 +00:00
actor - > hit . ceilhit = ceilColl ;
2020-12-03 21:04:07 +00:00
pSprite - > z + = ClipLow ( ceilZ - top , 0 ) ;
2021-09-04 10:52:02 +00:00
if ( actor - > zvel < 0 )
2021-08-23 17:21:41 +00:00
{
2021-09-04 10:52:02 +00:00
actor - > xvel = MulScale ( actor - > xvel , 0xc000 , 16 ) ;
actor - > yvel = MulScale ( actor - > yvel , 0xc000 , 16 ) ;
actor - > zvel = MulScale ( - actor - > zvel , 0x4000 , 16 ) ;
2020-12-03 21:04:07 +00:00
switch ( pSprite - > type )
{
2021-08-25 06:46:31 +00:00
case kThingZombieHead :
2021-09-04 10:52:02 +00:00
if ( abs ( actor - > zvel ) > 0x80000 )
2020-12-03 21:04:07 +00:00
{
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 607 , 0 , 0 ) ;
2020-12-03 21:04:07 +00:00
actDamageSprite ( nullptr , actor , kDamageFall , 80 ) ;
2021-08-25 06:46:31 +00:00
}
break ;
2020-12-03 21:04:07 +00:00
2021-08-25 06:46:31 +00:00
case kThingKickablePail :
2021-09-04 10:52:02 +00:00
if ( abs ( actor - > zvel ) > 0x80000 )
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 374 , 0 , 0 ) ;
2021-08-25 06:46:31 +00:00
break ;
2021-08-23 17:21:41 +00:00
}
}
}
2021-11-26 13:03:21 +00:00
else actor - > hit . ceilhit . setNone ( ) ;
2020-12-03 21:04:07 +00:00
2021-08-23 17:21:41 +00:00
if ( bottom > = floorZ )
{
2021-09-04 10:52:02 +00:00
int nVel = approxDist ( actor - > xvel , actor - > yvel ) ;
2021-08-23 17:21:41 +00:00
int nVelClipped = ClipHigh ( nVel , 0x11111 ) ;
2021-09-02 18:23:51 +00:00
Collision & coll = floorColl ;
2020-12-04 23:08:51 +00:00
if ( coll . type = = kHitSprite )
2021-08-23 17:21:41 +00:00
{
2021-11-26 13:03:21 +00:00
auto hitActor = coll . actor ( ) ;
2020-12-04 23:08:51 +00:00
auto hitSpr = & hitActor - > s ( ) ;
2021-12-18 18:19:28 +00:00
if ( ( hitSpr - > cstat & CSTAT_SPRITE_ALIGNMENT_MASK ) = = CSTAT_SPRITE_ALIGNMENT_FACING )
2021-08-23 17:21:41 +00:00
{
2021-09-04 10:52:02 +00:00
actor - > xvel + = MulScale ( 4 , pSprite - > x - hitSpr - > x , 2 ) ;
actor - > yvel + = MulScale ( 4 , pSprite - > y - hitSpr - > y , 2 ) ;
2021-08-29 17:09:29 +00:00
lhit = actor - > hit . hit ;
2021-08-23 17:21:41 +00:00
}
}
if ( nVel > 0 )
{
int t = DivScale ( nVelClipped , nVel , 16 ) ;
2021-09-04 10:52:02 +00:00
actor - > xvel - = MulScale ( t , actor - > xvel , 16 ) ;
actor - > yvel - = MulScale ( t , actor - > yvel , 16 ) ;
2021-08-23 17:21:41 +00:00
}
}
2021-09-04 10:52:02 +00:00
if ( actor - > xvel | | actor - > yvel )
pSprite - > ang = getangle ( actor - > xvel , actor - > yvel ) ;
2020-12-03 21:04:07 +00:00
return lhit ;
2019-09-19 22:42:45 +00:00
}
2020-12-03 21:04:07 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-12-05 09:40:13 +00:00
void MoveDude ( DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2020-12-04 13:25:04 +00:00
auto const pSprite = & actor - > s ( ) ;
auto const pXSprite = & actor - > x ( ) ;
2020-12-05 09:40:13 +00:00
PLAYER * pPlayer = nullptr ;
if ( actor - > IsPlayerActor ( ) ) pPlayer = & gPlayer [ pSprite - > type - kDudePlayer1 ] ;
if ( ! ( pSprite - > type > = kDudeBase & & pSprite - > type < kDudeMax ) )
2020-12-04 13:25:04 +00:00
{
2021-08-23 17:21:41 +00:00
Printf ( PRINT_HIGH , " %d: pSprite->type >= kDudeBase && pSprite->type < kDudeMax " , pSprite - > type ) ;
return ;
}
2020-12-04 13:25:04 +00:00
2020-12-05 09:40:13 +00:00
DUDEINFO * pDudeInfo = getDudeInfo ( pSprite - > type ) ;
2021-08-23 17:21:41 +00:00
int top , bottom ;
GetActorExtents ( actor , & top , & bottom ) ;
2020-12-05 09:40:13 +00:00
int bz = ( bottom - pSprite - > z ) / 4 ;
int tz = ( pSprite - > z - top ) / 4 ;
int wd = pSprite - > clipdist < < 2 ;
2021-11-23 23:16:02 +00:00
auto pSector = pSprite - > sector ( ) ;
2021-08-23 17:21:41 +00:00
int nAiStateType = ( pXSprite - > aiState ) ? pXSprite - > aiState - > stateType : - 1 ;
2021-07-19 21:15:26 +00:00
2021-11-23 23:16:02 +00:00
assert ( pSector ) ;
2020-12-04 13:25:04 +00:00
2021-09-04 10:52:02 +00:00
if ( actor - > xvel | | actor - > yvel )
2021-08-23 17:21:41 +00:00
{
if ( pPlayer & & gNoClip )
{
2021-09-04 10:52:02 +00:00
pSprite - > x + = actor - > xvel > > 12 ;
pSprite - > y + = actor - > yvel > > 12 ;
2021-11-23 23:16:02 +00:00
if ( ! FindSector ( pSprite - > x , pSprite - > y , & pSector ) )
pSector = pSprite - > sector ( ) ;
2021-08-23 17:21:41 +00:00
}
else
{
2021-11-16 17:15:56 +00:00
auto bakCstat = pSprite - > cstat ;
2021-12-18 15:09:58 +00:00
pSprite - > cstat & = ~ CSTAT_SPRITE_BLOCK_ALL ;
2021-11-26 13:03:21 +00:00
ClipMove ( pSprite - > pos , & pSector , actor - > xvel > > 12 , actor - > yvel > > 12 , wd , tz , bz , CLIPMASK0 , actor - > hit . hit ) ;
2021-11-23 23:16:02 +00:00
if ( pSector = = nullptr )
2021-08-23 17:21:41 +00:00
{
2021-11-23 23:16:02 +00:00
pSector = pSprite - > sector ( ) ;
2021-08-23 17:21:41 +00:00
if ( pSprite - > statnum = = kStatDude | | pSprite - > statnum = = kStatThing )
2021-09-16 19:10:23 +00:00
actDamageSprite ( actor , actor , kDamageFall , 1000 < < 4 ) ;
2021-08-23 17:21:41 +00:00
}
2021-11-23 23:16:02 +00:00
if ( pSector - > type > = kSectorPath & & pSector - > type < = kSectorRotate )
2021-08-23 17:21:41 +00:00
{
2021-11-23 23:16:02 +00:00
auto pSector2 = pSector ;
if ( pushmove ( & pSprite - > pos , & pSector2 , wd , tz , bz , CLIPMASK0 ) = = - 1 )
2021-08-23 17:21:41 +00:00
actDamageSprite ( actor , actor , kDamageFall , 1000 < < 4 ) ;
2021-11-23 23:16:02 +00:00
if ( pSector2 ! = nullptr )
pSector = pSector2 ;
2021-08-23 17:21:41 +00:00
}
2021-11-23 23:16:02 +00:00
assert ( pSector ) ;
2021-08-23 17:21:41 +00:00
pSprite - > cstat = bakCstat ;
}
2021-12-05 19:55:19 +00:00
auto & coll = actor - > hit . hit ;
2021-09-02 18:23:51 +00:00
switch ( coll . type )
2021-08-23 17:21:41 +00:00
{
case kHitSprite :
{
2021-11-26 13:03:21 +00:00
spritetype * pHitSprite = & coll . actor ( ) - > s ( ) ;
XSPRITE * pHitXSprite = coll . actor ( ) - > hasX ( ) ? & coll . actor ( ) - > x ( ) : nullptr ; ;
2020-12-04 13:25:04 +00:00
2021-11-26 13:03:21 +00:00
auto Owner = coll . actor ( ) - > GetOwner ( ) ;
2020-12-04 13:25:04 +00:00
2020-12-05 09:40:13 +00:00
if ( pHitSprite - > statnum = = kStatProjectile & & ! ( pHitSprite - > flags & 32 ) & & actor ! = Owner )
2021-08-23 17:21:41 +00:00
{
2021-11-25 22:28:28 +00:00
auto hitInfo = gHitInfo ;
gHitInfo . hitActor = actor ;
2021-11-26 13:03:21 +00:00
actImpactMissile ( coll . actor ( ) , 3 ) ;
2021-08-23 17:21:41 +00:00
gHitInfo = hitInfo ;
}
2020-12-05 09:40:13 +00:00
# ifdef NOONE_EXTENSIONS
2021-08-23 17:21:41 +00:00
if ( ! gModernMap & & pHitXSprite & & pHitXSprite - > Touch & & ! pHitXSprite - > state & & ! pHitXSprite - > isTriggered )
2021-11-26 13:03:21 +00:00
trTriggerSprite ( coll . actor ( ) , kCmdSpriteTouch ) ;
2020-12-05 09:40:13 +00:00
# else
2021-08-25 06:46:31 +00:00
if ( pHitXSprite & & pHitXSprite - > Touch & & ! pHitXSprite - > state & & ! pHitXSprite - > isTriggered )
trTriggerSprite ( coll . actor , kCmdSpriteTouch ) ;
2020-12-05 09:40:13 +00:00
# endif
2019-12-23 20:10:28 +00:00
2021-08-23 17:21:41 +00:00
if ( pDudeInfo - > lockOut & & pHitXSprite & & pHitXSprite - > Push & & ! pHitXSprite - > key & & ! pHitXSprite - > DudeLockout & & ! pHitXSprite - > state & & ! pHitXSprite - > busy & & ! pPlayer )
2021-11-26 13:03:21 +00:00
trTriggerSprite ( coll . actor ( ) , kCmdSpritePush ) ;
2019-10-11 21:59:39 +00:00
2021-08-23 17:21:41 +00:00
break ;
}
case kHitWall :
{
2021-11-26 13:03:21 +00:00
walltype * pHitWall = coll . hitWall ;
2020-12-05 09:40:13 +00:00
XWALL * pHitXWall = nullptr ;
2021-11-19 18:33:38 +00:00
if ( pHitWall - > hasX ( ) ) pHitXWall = & pHitWall - > xw ( ) ;
2020-12-04 23:08:51 +00:00
2021-08-23 17:21:41 +00:00
if ( pDudeInfo - > lockOut & & pHitXWall & & pHitXWall - > triggerPush & & ! pHitXWall - > key & & ! pHitXWall - > dudeLockout & & ! pHitXWall - > state & & ! pHitXWall - > busy & & ! pPlayer )
2021-11-19 14:46:20 +00:00
trTriggerWall ( pHitWall , kCmdWallPush ) ;
2020-12-04 13:25:04 +00:00
2021-11-23 22:04:21 +00:00
if ( pHitWall - > twoSided ( ) )
2021-08-23 17:21:41 +00:00
{
2021-11-19 17:08:05 +00:00
sectortype * pHitSector = pHitWall - > nextSector ( ) ;
XSECTOR * pHitXSector = pHitSector - > hasX ( ) ? & pHitSector - > xs ( ) : nullptr ;
2021-08-23 17:21:41 +00:00
if ( pDudeInfo - > lockOut & & pHitXSector & & pHitXSector - > Wallpush & & ! pHitXSector - > Key & & ! pHitXSector - > dudeLockout & & ! pHitXSector - > state & & ! pHitXSector - > busy & & ! pPlayer )
2021-11-19 17:27:50 +00:00
trTriggerSector ( pHitSector , kCmdSectorPush ) ;
2021-08-23 17:21:41 +00:00
if ( top < pHitSector - > ceilingz | | bottom > pHitSector - > floorz )
{
// ???
}
}
2021-11-21 08:45:50 +00:00
actWallBounceVector ( ( int * ) & actor - > xvel , ( int * ) & actor - > yvel , pHitWall , 0 ) ;
2021-08-23 17:21:41 +00:00
break ;
}
}
}
else
{
2021-11-23 23:16:02 +00:00
assert ( pSector ) ;
FindSector ( pSprite - > x , pSprite - > y , pSprite - > z , & pSector ) ;
2021-08-23 17:21:41 +00:00
}
2021-11-19 17:08:05 +00:00
XSECTOR * pXSector = pSector - > hasX ( ) ? & pSector - > xs ( ) : nullptr ;
2021-11-23 23:16:02 +00:00
if ( pSprite - > sector ( ) ! = pSector )
2021-08-23 17:21:41 +00:00
{
2021-11-23 23:38:07 +00:00
assert ( pSprite - > sector ( ) ) ;
2021-11-19 17:08:05 +00:00
auto pOldSector = pSprite - > sector ( ) ;
XSECTOR * pXOldSector = pOldSector - > hasX ( ) ? & pOldSector - > xs ( ) : nullptr ;
if ( pXOldSector & & pXOldSector - > Exit & & ( pPlayer | | ! pXOldSector - > dudeLockout ) )
2021-11-19 17:27:50 +00:00
trTriggerSector ( pOldSector , kCmdSectorExit ) ;
2021-11-23 23:16:02 +00:00
ChangeActorSect ( actor , pSector ) ;
2021-08-23 17:21:41 +00:00
2020-12-05 09:40:13 +00:00
if ( pXSector & & pXSector - > Enter & & ( pPlayer | | ! pXSector - > dudeLockout ) )
2020-12-04 13:25:04 +00:00
{
2021-11-19 17:08:05 +00:00
if ( pSector - > type = = kSectorTeleport )
2021-09-05 06:41:44 +00:00
pXSector - > actordata = actor ;
2021-11-19 17:27:50 +00:00
trTriggerSector ( pSector , kCmdSectorEnter ) ;
2021-08-23 17:21:41 +00:00
}
2021-11-23 23:16:02 +00:00
pSector = pSprite - > sector ( ) ;
2021-08-23 17:21:41 +00:00
}
int bUnderwater = 0 ;
int bDepth = 0 ;
2021-11-19 17:08:05 +00:00
if ( pXSector )
2021-08-23 17:21:41 +00:00
{
if ( pXSector - > Underwater ) bUnderwater = 1 ;
if ( pXSector - > Depth ) bDepth = 1 ;
}
2021-12-05 23:50:33 +00:00
DCoreActor * pUpperLink = pSector - > upperLink ;
DCoreActor * pLowerLink = pSector - > lowerLink ;
2021-12-21 22:18:23 +00:00
if ( pUpperLink & & ( pUpperLink - > spr . type = = kMarkerUpWater | | pUpperLink - > spr . type = = kMarkerUpGoo ) ) bDepth = 1 ;
if ( pLowerLink & & ( pLowerLink - > spr . type = = kMarkerLowWater | | pLowerLink - > spr . type = = kMarkerLowGoo ) ) bDepth = 1 ;
2021-08-23 17:21:41 +00:00
if ( pPlayer ) wd + = 16 ;
2021-09-04 10:52:02 +00:00
if ( actor - > zvel ) pSprite - > z + = actor - > zvel > > 8 ;
2020-12-04 23:08:51 +00:00
2021-09-02 18:23:51 +00:00
int ceilZ , floorZ ;
Collision ceilColl , floorColl ;
2021-09-04 18:19:38 +00:00
GetZRange ( actor , & ceilZ , & ceilColl , & floorZ , & floorColl , wd , CLIPMASK0 , PARALLAXCLIP_CEILING | PARALLAXCLIP_FLOOR ) ;
2021-08-23 17:21:41 +00:00
GetActorExtents ( actor , & top , & bottom ) ;
if ( pSprite - > flags & 2 )
{
int vc = 58254 ;
if ( bDepth )
{
if ( bUnderwater )
{
2021-11-23 23:16:02 +00:00
int cz = getceilzofslopeptr ( pSector , pSprite - > x , pSprite - > y ) ;
2021-08-23 17:21:41 +00:00
if ( cz > top )
2020-12-05 09:40:13 +00:00
vc + = ( ( bottom - cz ) * - 80099 ) / ( bottom - top ) ;
2021-08-23 17:21:41 +00:00
else
vc = 0 ;
}
else
{
2021-11-23 23:16:02 +00:00
int fz = getflorzofslopeptr ( pSector , pSprite - > x , pSprite - > y ) ;
2021-08-23 17:21:41 +00:00
if ( fz < bottom )
2020-12-05 09:40:13 +00:00
vc + = ( ( bottom - fz ) * - 80099 ) / ( bottom - top ) ;
2021-08-23 17:21:41 +00:00
}
}
else
{
if ( bUnderwater )
vc = 0 ;
else if ( bottom > = floorZ )
2021-08-25 06:46:31 +00:00
vc = 0 ;
2021-08-23 17:21:41 +00:00
}
if ( vc )
{
2020-12-05 09:40:13 +00:00
pSprite - > z + = ( ( vc * 4 ) / 2 ) > > 8 ;
2021-09-04 10:52:02 +00:00
actor - > zvel + = vc ;
2021-08-23 17:21:41 +00:00
}
}
2021-09-04 10:52:02 +00:00
if ( pPlayer & & actor - > zvel > 0x155555 & & ! pPlayer - > fallScream & & pXSprite - > height > 0 )
2021-08-23 17:21:41 +00:00
{
const bool playerAlive = ( pXSprite - > health > 0 ) | | VanillaMode ( ) ; // only trigger falling scream if player is alive or vanilla mode
if ( playerAlive )
{
pPlayer - > fallScream = 1 ;
2021-09-16 19:59:39 +00:00
sfxPlay3DSound ( actor , 719 , 0 , 0 ) ;
2021-08-23 17:21:41 +00:00
}
}
vec3_t const oldpos = pSprite - > pos ;
2021-09-04 07:37:17 +00:00
int nLink = CheckLink ( actor ) ;
2021-08-23 17:21:41 +00:00
if ( nLink )
{
2021-09-04 18:19:38 +00:00
GetZRange ( actor , & ceilZ , & ceilColl , & floorZ , & floorColl , wd , CLIPMASK0 , PARALLAXCLIP_CEILING | PARALLAXCLIP_FLOOR ) ;
2021-08-23 17:21:41 +00:00
if ( pPlayer )
playerCorrectInertia ( pPlayer , & oldpos ) ;
2020-12-05 09:40:13 +00:00
switch ( nLink )
2020-12-04 13:25:04 +00:00
{
2021-08-23 17:21:41 +00:00
case kMarkerLowStack :
if ( pPlayer = = gView )
2021-12-17 21:36:59 +00:00
gotpic . Set ( pSprite - > sector ( ) - > floorpicnum ) ;
2021-08-23 17:21:41 +00:00
break ;
case kMarkerUpStack :
if ( pPlayer = = gView )
2021-12-17 21:36:59 +00:00
gotpic . Set ( pSprite - > sector ( ) - > ceilingpicnum ) ;
2021-08-23 17:21:41 +00:00
break ;
case kMarkerLowWater :
case kMarkerLowGoo :
pXSprite - > medium = kMediumNormal ;
2020-12-05 09:40:13 +00:00
if ( pPlayer )
2020-12-04 13:25:04 +00:00
{
2021-08-23 17:21:41 +00:00
pPlayer - > posture = 0 ;
pPlayer - > bubbleTime = 0 ;
2020-12-05 09:40:13 +00:00
if ( ! pPlayer - > cantJump & & ( pPlayer - > input . actions & SB_JUMP ) )
2020-12-04 13:25:04 +00:00
{
2021-09-04 10:52:02 +00:00
actor - > zvel = - 0x6aaaa ;
2021-08-23 17:21:41 +00:00
pPlayer - > cantJump = 1 ;
}
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 721 , - 1 , 0 ) ;
2020-12-05 09:40:13 +00:00
}
else
2020-12-04 13:25:04 +00:00
{
2020-12-05 09:40:13 +00:00
switch ( pSprite - > type )
2020-12-04 13:25:04 +00:00
{
2020-12-05 09:40:13 +00:00
case kDudeCultistTommy :
case kDudeCultistShotgun :
2021-09-16 19:59:39 +00:00
aiNewState ( actor , & cultistGoto ) ;
2020-12-05 09:40:13 +00:00
break ;
case kDudeGillBeast :
2021-09-16 19:59:39 +00:00
aiNewState ( actor , & gillBeastGoto ) ;
2020-12-05 09:40:13 +00:00
pSprite - > flags | = 6 ;
break ;
case kDudeBoneEel :
2021-09-16 19:59:39 +00:00
actKillDude ( actor , actor , kDamageFall , 1000 < < 4 ) ;
2021-08-25 06:46:31 +00:00
break ;
2021-08-23 17:21:41 +00:00
}
2021-08-25 06:46:31 +00:00
# ifdef NOONE_EXTENSIONS
2021-08-29 07:44:08 +00:00
if ( actor - > IsDudeActor ( ) & & pXSprite - > health > 0 & & aiInPatrolState ( nAiStateType ) )
2021-08-29 12:36:40 +00:00
aiPatrolState ( actor , kAiStatePatrolMoveL ) ; // continue patrol when going from water
2021-08-25 06:46:31 +00:00
# endif
2021-08-23 17:21:41 +00:00
}
break ;
case kMarkerUpWater :
case kMarkerUpGoo :
{
int chance = 0xa00 ; int medium = kMediumWater ;
2020-12-05 09:40:13 +00:00
if ( nLink = = kMarkerUpGoo ) {
2021-08-23 17:21:41 +00:00
medium = kMediumGoo ;
chance = 0x400 ;
}
2020-01-26 11:19:01 +00:00
2021-08-23 17:21:41 +00:00
pXSprite - > medium = medium ;
2019-09-19 22:42:45 +00:00
2021-08-23 17:21:41 +00:00
if ( pPlayer )
{
2020-12-05 09:40:13 +00:00
# ifdef NOONE_EXTENSIONS
2021-08-23 17:21:41 +00:00
// look for palette in data2 of marker. If value <= 0, use default ones.
2021-08-25 06:46:31 +00:00
if ( gModernMap )
2020-12-05 09:40:13 +00:00
{
2021-08-23 17:21:41 +00:00
pPlayer - > nWaterPal = 0 ;
2021-12-05 23:50:33 +00:00
auto pUpper = barrier_cast < DBloodActor * > ( pSector - > upperLink ) ;
2021-08-25 06:46:31 +00:00
if ( pUpper & & pUpper - > hasX ( ) ) pPlayer - > nWaterPal = pUpper - > x ( ) . data2 ;
2021-08-23 17:21:41 +00:00
}
2021-08-25 06:46:31 +00:00
# endif
2021-08-23 17:21:41 +00:00
pPlayer - > posture = 1 ;
pXSprite - > burnTime = 0 ;
2021-09-04 10:52:02 +00:00
pPlayer - > bubbleTime = abs ( actor - > zvel ) > > 12 ;
2021-08-27 07:44:47 +00:00
evPostActor ( actor , 0 , kCallbackPlayerBubble ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 720 , - 1 , 0 ) ;
2021-08-23 17:21:41 +00:00
}
else
{
2020-12-05 09:40:13 +00:00
switch ( pSprite - > type )
2020-12-04 13:25:04 +00:00
{
2021-08-23 17:21:41 +00:00
case kDudeCultistTommy :
case kDudeCultistShotgun :
pXSprite - > burnTime = 0 ;
2021-08-27 07:44:47 +00:00
evPostActor ( actor , 0 , kCallbackEnemeyBubble ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 720 , - 1 , 0 ) ;
2021-08-23 17:21:41 +00:00
aiNewState ( actor , & cultistSwimGoto ) ;
break ;
case kDudeBurningCultist :
{
const bool fixRandomCultist = ! cl_bloodvanillaenemies & & ( pSprite - > inittype > = kDudeBase ) & & ( pSprite - > inittype < kDudeMax ) & & ! VanillaMode ( ) ; // fix burning cultists randomly switching types underwater
if ( Chance ( chance ) )
pSprite - > type = kDudeCultistTommy ;
else
pSprite - > type = kDudeCultistShotgun ;
if ( fixRandomCultist ) // fix burning cultists randomly switching types underwater
pSprite - > type = pSprite - > inittype ; // restore back to spawned cultist type
pXSprite - > burnTime = 0 ;
2021-08-27 07:44:47 +00:00
evPostActor ( actor , 0 , kCallbackEnemeyBubble ) ;
2021-09-16 19:59:39 +00:00
sfxPlay3DSound ( actor , 720 , - 1 , 0 ) ;
2021-08-25 06:46:31 +00:00
aiNewState ( actor , & cultistSwimGoto ) ;
2021-08-23 17:21:41 +00:00
break ;
}
case kDudeZombieAxeNormal :
pXSprite - > burnTime = 0 ;
2021-08-27 07:44:47 +00:00
evPostActor ( actor , 0 , kCallbackEnemeyBubble ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 720 , - 1 , 0 ) ;
2021-08-23 17:21:41 +00:00
aiNewState ( actor , & zombieAGoto ) ;
break ;
case kDudeZombieButcher :
pXSprite - > burnTime = 0 ;
2021-08-27 07:44:47 +00:00
evPostActor ( actor , 0 , kCallbackEnemeyBubble ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 720 , - 1 , 0 ) ;
2021-08-23 17:21:41 +00:00
aiNewState ( actor , & zombieFGoto ) ;
break ;
case kDudeGillBeast :
pXSprite - > burnTime = 0 ;
2021-08-27 07:44:47 +00:00
evPostActor ( actor , 0 , kCallbackEnemeyBubble ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 720 , - 1 , 0 ) ;
2021-08-23 17:21:41 +00:00
aiNewState ( actor , & gillBeastSwimGoto ) ;
pSprite - > flags & = ~ 6 ;
break ;
case kDudeGargoyleFlesh :
case kDudeHellHound :
case kDudeSpiderBrown :
case kDudeSpiderRed :
case kDudeSpiderBlack :
case kDudeBat :
case kDudeRat :
case kDudeBurningInnocent :
2020-12-05 22:49:51 +00:00
actKillDude ( actor , actor , kDamageFall , 1000 < < 4 ) ;
2021-08-23 17:21:41 +00:00
break ;
}
2021-08-25 06:46:31 +00:00
# ifdef NOONE_EXTENSIONS
2021-08-23 17:21:41 +00:00
if ( gModernMap ) {
if ( pSprite - > type = = kDudeModernCustom ) {
2021-07-19 21:15:26 +00:00
2021-08-27 07:44:47 +00:00
evPostActor ( actor , 0 , kCallbackEnemeyBubble ) ;
2021-05-06 08:24:29 +00:00
if ( ! canSwim ( actor ) ) actKillDude ( actor , actor , kDamageFall , 1000 < < 4 ) ;
2020-12-04 13:25:04 +00:00
break ;
2021-08-23 17:21:41 +00:00
}
// continue patrol when fall into water
2021-08-29 07:44:08 +00:00
if ( actor - > IsDudeActor ( ) & & pXSprite - > health > 0 & & aiInPatrolState ( nAiStateType ) )
2021-08-29 12:36:40 +00:00
aiPatrolState ( actor , kAiStatePatrolMoveW ) ;
2021-08-23 17:21:41 +00:00
}
2021-08-25 06:46:31 +00:00
# endif
2021-08-23 17:21:41 +00:00
}
break ;
}
2021-08-25 06:46:31 +00:00
}
}
2021-08-23 17:21:41 +00:00
GetActorExtents ( actor , & top , & bottom ) ;
if ( pPlayer & & bottom > = floorZ )
{
int floorZ2 = floorZ ;
2021-09-02 18:23:51 +00:00
auto floorColl2 = floorColl ;
2021-09-04 18:19:38 +00:00
GetZRange ( actor , & ceilZ , & ceilColl , & floorZ , & floorColl , pSprite - > clipdist < < 2 , CLIPMASK0 , PARALLAXCLIP_CEILING | PARALLAXCLIP_FLOOR ) ;
2021-08-23 17:21:41 +00:00
if ( bottom < = floorZ & & pSprite - > z - floorZ2 < bz )
{
floorZ = floorZ2 ;
2021-09-02 18:23:51 +00:00
floorColl = floorColl2 ;
2021-08-23 17:21:41 +00:00
}
}
if ( floorZ < = bottom )
{
2021-08-29 17:09:29 +00:00
actor - > hit . florhit = floorColl ;
2020-12-05 09:40:13 +00:00
pSprite - > z + = floorZ - bottom ;
2021-11-20 18:10:02 +00:00
int v30 = actor - > zvel - pSprite - > sector ( ) - > velFloor ;
2021-08-23 17:21:41 +00:00
if ( v30 > 0 )
{
2021-11-23 23:12:37 +00:00
int vax = actFloorBounceVector ( ( int * ) & actor - > xvel , ( int * ) & actor - > yvel , ( int * ) & v30 , pSprite - > sector ( ) , 0 ) ;
2021-08-23 17:21:41 +00:00
int nDamage = MulScale ( vax , vax , 30 ) ;
if ( pPlayer )
{
pPlayer - > fallScream = 0 ;
2019-10-20 14:50:47 +00:00
2020-12-05 09:40:13 +00:00
if ( nDamage > ( 15 < < 4 ) & & ( pSprite - > flags & 4 ) )
2021-08-23 17:21:41 +00:00
playerLandingSound ( pPlayer ) ;
2020-12-05 09:40:13 +00:00
if ( nDamage > ( 30 < < 4 ) )
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 701 , 0 , 0 ) ;
2021-08-23 17:21:41 +00:00
}
2020-12-05 09:40:13 +00:00
nDamage - = 100 < < 4 ;
2021-08-23 17:21:41 +00:00
if ( nDamage > 0 )
actDamageSprite ( actor , actor , kDamageFall , nDamage ) ;
2021-09-04 10:52:02 +00:00
actor - > zvel = v30 ;
if ( abs ( actor - > zvel ) < 0x10000 )
2021-08-23 17:21:41 +00:00
{
2021-11-20 18:10:02 +00:00
actor - > zvel = pSprite - > sector ( ) - > velFloor ;
2021-08-23 17:21:41 +00:00
pSprite - > flags & = ~ 4 ;
}
else
pSprite - > flags | = 4 ;
2021-08-27 17:12:22 +00:00
2021-08-27 19:49:18 +00:00
switch ( tileGetSurfType ( floorColl ) )
2021-08-23 17:21:41 +00:00
{
case kSurfWater :
2021-11-23 23:41:19 +00:00
gFX . fxSpawnActor ( FX_9 , pSprite - > sector ( ) , pSprite - > x , pSprite - > y , floorZ , 0 ) ;
2021-08-23 17:21:41 +00:00
break ;
case kSurfLava :
{
2021-11-23 23:41:19 +00:00
auto pFX = gFX . fxSpawnActor ( FX_10 , pSprite - > sector ( ) , pSprite - > x , pSprite - > y , floorZ , 0 ) ;
2021-08-23 17:21:41 +00:00
if ( pFX )
{
2021-08-30 18:32:14 +00:00
auto pFXs = & pFX - > s ( ) ;
2021-08-23 17:21:41 +00:00
for ( int i = 0 ; i < 7 ; i + + )
{
2021-11-23 23:41:19 +00:00
auto pFX2 = gFX . fxSpawnActor ( FX_14 , pFXs - > sector ( ) , pFXs - > x , pFXs - > y , pFXs - > z , 0 ) ;
2021-08-23 17:21:41 +00:00
if ( pFX2 )
{
2021-09-04 10:52:02 +00:00
pFX2 - > xvel = Random2 ( 0x6aaaa ) ;
pFX2 - > yvel = Random2 ( 0x6aaaa ) ;
pFX2 - > zvel = - ( int ) Random ( 0xd5555 ) ;
2021-08-23 17:21:41 +00:00
}
}
}
break ;
}
}
}
2021-09-04 10:52:02 +00:00
else if ( actor - > zvel = = 0 )
2021-08-23 17:21:41 +00:00
pSprite - > flags & = ~ 4 ;
}
else
{
2021-11-26 13:03:21 +00:00
actor - > hit . florhit . setNone ( ) ;
2019-10-20 14:50:47 +00:00
2020-12-05 09:40:13 +00:00
if ( pSprite - > flags & 2 )
2021-08-23 17:21:41 +00:00
pSprite - > flags | = 4 ;
}
if ( top < = ceilZ )
{
2021-08-29 17:09:29 +00:00
actor - > hit . ceilhit = ceilColl ;
2020-12-05 09:40:13 +00:00
pSprite - > z + = ClipLow ( ceilZ - top , 0 ) ;
2019-10-20 14:50:47 +00:00
2021-09-04 10:52:02 +00:00
if ( actor - > zvel < = 0 & & ( pSprite - > flags & 4 ) )
actor - > zvel = MulScale ( - actor - > zvel , 0x2000 , 16 ) ;
2021-08-23 17:21:41 +00:00
}
else
2021-11-26 13:03:21 +00:00
actor - > hit . ceilhit . setNone ( ) ;
2020-12-04 23:08:51 +00:00
2020-12-05 09:40:13 +00:00
GetActorExtents ( actor , & top , & bottom ) ;
2019-09-19 22:42:45 +00:00
2020-12-05 09:40:13 +00:00
pXSprite - > height = ClipLow ( floorZ - bottom , 0 ) > > 8 ;
2021-09-04 10:52:02 +00:00
if ( actor - > xvel | | actor - > yvel )
2021-08-23 17:21:41 +00:00
{
2021-09-02 18:23:51 +00:00
if ( floorColl . type = = kHitSprite )
2021-08-23 17:21:41 +00:00
{
2021-11-26 13:03:21 +00:00
auto hitAct = floorColl . actor ( ) ;
2021-12-21 22:18:23 +00:00
if ( ( hitAct - > spr . cstat & CSTAT_SPRITE_ALIGNMENT_MASK ) = = CSTAT_SPRITE_ALIGNMENT_FACING )
2021-08-23 17:21:41 +00:00
{
2021-12-21 22:18:23 +00:00
actor - > xvel + = MulScale ( 4 , pSprite - > x - hitAct - > spr . x , 2 ) ;
actor - > yvel + = MulScale ( 4 , pSprite - > y - hitAct - > spr . y , 2 ) ;
2021-08-23 17:21:41 +00:00
return ;
}
}
2021-11-19 17:46:06 +00:00
if ( IsUnderwaterSector ( pSprite - > sector ( ) ) )
2021-08-23 17:21:41 +00:00
return ;
if ( pXSprite - > height > = 0x100 )
return ;
int nDrag = gDudeDrag ;
if ( pXSprite - > height > 0 )
nDrag - = scale ( gDudeDrag , pXSprite - > height , 0x100 ) ;
2021-09-04 10:52:02 +00:00
actor - > xvel - = mulscale16r ( actor - > xvel , nDrag ) ;
actor - > yvel - = mulscale16r ( actor - > yvel , nDrag ) ;
2021-08-23 17:21:41 +00:00
2021-09-04 10:52:02 +00:00
if ( approxDist ( actor - > xvel , actor - > yvel ) < 0x1000 )
actor - > xvel = actor - > yvel = 0 ;
2021-08-23 17:21:41 +00:00
}
2019-09-19 22:42:45 +00:00
}
2020-12-05 09:40:13 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-12-05 11:17:28 +00:00
int MoveMissile ( DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2020-12-05 11:17:28 +00:00
auto pSprite = & actor - > s ( ) ;
auto Owner = actor - > GetOwner ( ) ;
int cliptype = - 1 ;
2021-12-18 18:19:28 +00:00
ESpriteFlags bakCstat = 0 ;
2020-12-05 11:17:28 +00:00
spritetype * pOwner = nullptr ;
if ( Owner & & Owner - > IsDudeActor ( ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 11:17:28 +00:00
pOwner = & Owner - > s ( ) ;
2021-12-18 19:41:15 +00:00
bakCstat = pOwner - > cstat ;
2021-12-18 15:09:58 +00:00
pOwner - > cstat & = ~ CSTAT_SPRITE_BLOCK_ALL ;
2021-08-25 06:46:31 +00:00
}
2021-05-05 14:43:42 +00:00
gHitInfo . clearObj ( ) ;
2020-12-05 11:17:28 +00:00
if ( pSprite - > type = = kMissileFlameSpray ) actAirDrag ( actor , 0x1000 ) ;
2021-09-04 10:52:02 +00:00
if ( actor - > GetTarget ( ) ! = nullptr & & ( actor - > xvel | | actor - > yvel | | actor - > zvel ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 11:17:28 +00:00
auto target = actor - > GetTarget ( ) ;
spritetype * pTarget = & target - > s ( ) ;
XSPRITE * pXTarget = target - > hasX ( ) ? & target - > x ( ) : nullptr ;
2021-08-23 17:21:41 +00:00
if ( pTarget - > statnum = = kStatDude & & pXTarget & & pXTarget - > health > 0 )
{
2020-12-05 11:17:28 +00:00
int nTargetAngle = getangle ( - ( pTarget - > y - pSprite - > y ) , pTarget - > x - pSprite - > x ) ;
2021-08-23 17:21:41 +00:00
int vx = missileInfo [ pSprite - > type - kMissileBase ] . velocity ;
int vy = 0 ;
2020-12-05 11:17:28 +00:00
RotatePoint ( & vx , & vy , ( nTargetAngle + 1536 ) & 2047 , 0 , 0 ) ;
2021-09-04 10:52:02 +00:00
actor - > xvel = vx ;
actor - > yvel = vy ;
2020-12-05 11:17:28 +00:00
int dz = pTarget - > z - pSprite - > z ;
int deltaz = dz / 10 ;
if ( pTarget - > z < pSprite - > z ) deltaz = - deltaz ;
2021-09-04 10:52:02 +00:00
actor - > zvel + = deltaz ;
2021-08-23 17:21:41 +00:00
}
}
2021-09-04 10:52:02 +00:00
int vx = actor - > xvel > > 12 ;
int vy = actor - > yvel > > 12 ;
int vz = actor - > zvel > > 8 ;
2021-08-23 17:21:41 +00:00
int top , bottom ;
2020-12-05 11:17:28 +00:00
GetActorExtents ( actor , & top , & bottom ) ;
2021-08-23 17:21:41 +00:00
int i = 1 ;
const int bakCompat = enginecompatibility_mode ;
const bool isFlameSprite = ( pSprite - > type = = kMissileFlameSpray | | pSprite - > type = = kMissileFlameHound ) ; // do not use accurate clipmove for flame based sprites (changes damage too much)
while ( 1 )
{
2021-10-30 10:26:35 +00:00
vec3_t pos = pSprite - > pos ;
2021-11-23 23:21:08 +00:00
auto pSector2 = pSprite - > sector ( ) ;
2021-11-16 17:15:56 +00:00
const auto bakSpriteCstat = pSprite - > cstat ;
2021-08-23 17:21:41 +00:00
if ( pOwner & & ! isFlameSprite & & ! cl_bloodvanillaexplosions & & ! VanillaMode ( ) )
{
enginecompatibility_mode = ENGINECOMPATIBILITY_NONE ; // improved clipmove accuracy
2021-12-18 15:09:58 +00:00
pSprite - > cstat & = ~ CSTAT_SPRITE_BLOCK_ALL ; // remove self collisions for accurate clipmove
2021-08-23 17:21:41 +00:00
}
2021-11-26 13:03:21 +00:00
Collision clipmoveresult ;
2021-12-22 09:41:47 +00:00
ClipMove ( pos , & pSector2 , vx , vy , pSprite - > clipdist < < 2 , ( pos . Z - top ) / 4 , ( bottom - pos . Z ) / 4 , CLIPMASK0 , clipmoveresult , 1 ) ;
2021-08-23 17:21:41 +00:00
enginecompatibility_mode = bakCompat ; // restore
pSprite - > cstat = bakSpriteCstat ;
2021-11-23 23:21:08 +00:00
auto pSector = pSector2 ;
if ( pSector2 = = nullptr )
2021-08-23 17:21:41 +00:00
{
2020-12-05 11:17:28 +00:00
cliptype = - 1 ;
2021-08-23 17:21:41 +00:00
break ;
}
2020-12-05 11:17:28 +00:00
if ( clipmoveresult . type = = kHitSprite )
2021-08-23 17:21:41 +00:00
{
2021-11-26 13:03:21 +00:00
gHitInfo . hitActor = clipmoveresult . actor ( ) ;
2020-12-05 11:17:28 +00:00
cliptype = 3 ;
2021-08-25 06:46:31 +00:00
}
2020-12-05 11:17:28 +00:00
else if ( clipmoveresult . type = = kHitWall )
2021-08-25 06:46:31 +00:00
{
2021-11-26 13:03:21 +00:00
gHitInfo . hitWall = clipmoveresult . hitWall ;
2021-11-23 16:00:00 +00:00
if ( ! gHitInfo . hitWall - > twoSided ( ) ) cliptype = 0 ;
2021-08-25 06:46:31 +00:00
else
{
int32_t fz , cz ;
2021-12-22 09:40:26 +00:00
getzsofslopeptr ( clipmoveresult . hitWall - > nextSector ( ) , pos . X , pos . Y , & cz , & fz ) ;
2021-12-22 09:41:47 +00:00
if ( pos . Z < = cz | | pos . Z > = fz ) cliptype = 0 ;
2020-12-05 11:17:28 +00:00
else cliptype = 4 ;
2021-08-23 17:21:41 +00:00
}
2021-08-25 06:46:31 +00:00
}
2020-12-05 11:17:28 +00:00
if ( cliptype = = 4 )
2021-08-23 17:21:41 +00:00
{
2021-11-26 13:03:21 +00:00
walltype * pWall = clipmoveresult . hitWall ;
2021-11-19 14:46:20 +00:00
if ( pWall - > hasX ( ) )
2021-08-23 17:21:41 +00:00
{
2021-11-19 00:13:33 +00:00
XWALL * pXWall = & pWall - > xw ( ) ;
2021-08-23 17:21:41 +00:00
if ( pXWall - > triggerVector )
{
2021-11-19 14:46:20 +00:00
trTriggerWall ( pWall , kCmdWallImpact ) ;
2021-12-18 14:36:50 +00:00
if ( ! ( pWall - > cstat & CSTAT_WALL_BLOCK_HITSCAN ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 11:17:28 +00:00
cliptype = - 1 ;
2021-08-23 17:21:41 +00:00
if ( i - - > 0 )
continue ;
2020-12-05 11:17:28 +00:00
cliptype = 0 ;
2021-08-23 17:21:41 +00:00
break ;
}
}
}
}
2020-12-05 11:17:28 +00:00
if ( cliptype > = 0 & & cliptype ! = 3 )
2021-08-23 17:21:41 +00:00
{
2021-09-04 10:52:02 +00:00
int nAngle = getangle ( actor - > xvel , actor - > yvel ) ;
2021-12-22 09:36:09 +00:00
pos . X - = MulScale ( Cos ( nAngle ) , 16 , 30 ) ;
2021-12-22 09:40:26 +00:00
pos . Y - = MulScale ( Sin ( nAngle ) , 16 , 30 ) ;
2021-09-04 10:52:02 +00:00
int nVel = approxDist ( actor - > xvel , actor - > yvel ) ;
vz - = scale ( 0x100 , actor - > zvel , nVel ) ;
2021-12-22 09:40:26 +00:00
updatesector ( pos . X , pos . Y , & pSector ) ;
2021-11-23 23:21:08 +00:00
pSector2 = pSector ;
2021-08-23 17:21:41 +00:00
}
2021-09-02 18:23:51 +00:00
int ceilZ , floorZ ;
Collision ceilColl , floorColl ;
2021-12-22 09:41:47 +00:00
GetZRangeAtXYZ ( pos . X , pos . Y , pos . Z , pSector2 , & ceilZ , & ceilColl , & floorZ , & floorColl , pSprite - > clipdist < < 2 , CLIPMASK0 ) ;
2020-12-05 11:17:28 +00:00
GetActorExtents ( actor , & top , & bottom ) ;
2021-08-23 17:21:41 +00:00
top + = vz ;
bottom + = vz ;
if ( bottom > = floorZ )
{
2021-08-29 17:09:29 +00:00
actor - > hit . florhit = floorColl ;
2020-12-05 11:17:28 +00:00
vz + = floorZ - bottom ;
cliptype = 2 ;
2021-08-23 17:21:41 +00:00
}
if ( top < = ceilZ )
{
2021-08-29 17:09:29 +00:00
actor - > hit . ceilhit = ceilColl ;
2020-12-05 11:17:28 +00:00
vz + = ClipLow ( ceilZ - top , 0 ) ;
cliptype = 1 ;
2021-08-23 17:21:41 +00:00
}
2021-10-30 10:26:35 +00:00
pSprite - > pos = pos ;
pSprite - > z + = vz ;
2021-12-22 09:40:26 +00:00
updatesector ( pos . X , pos . Y , & pSector ) ;
2021-11-23 23:21:08 +00:00
if ( pSector ! = nullptr & & pSector ! = pSprite - > sector ( ) )
2021-08-23 17:21:41 +00:00
{
2021-11-23 23:21:08 +00:00
assert ( pSector ) ;
ChangeActorSect ( actor , pSector ) ;
2021-08-23 17:21:41 +00:00
}
2021-09-04 07:37:17 +00:00
CheckLink ( actor ) ;
2021-11-25 22:28:28 +00:00
gHitInfo . hitSector = pSprite - > sector ( ) ;
2021-12-22 09:36:09 +00:00
gHitInfo . hitpos . X = pSprite - > x ;
2021-12-22 09:40:26 +00:00
gHitInfo . hitpos . Y = pSprite - > y ;
2021-12-22 09:41:47 +00:00
gHitInfo . hitpos . Z = pSprite - > z ;
2021-08-23 17:21:41 +00:00
break ;
}
2020-12-05 11:17:28 +00:00
if ( pOwner ) pOwner - > cstat = bakCstat ;
return cliptype ;
2019-09-19 22:42:45 +00:00
}
2020-12-05 11:17:28 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void actExplodeSprite ( DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2020-12-05 11:17:28 +00:00
if ( ! actor - > hasX ( ) ) return ;
auto pSprite = & actor - > s ( ) ;
auto pXSprite = & actor - > x ( ) ;
//auto Owner = actor->GetOwner();
if ( pSprite - > statnum = = kStatExplosion ) return ;
2021-11-28 09:24:42 +00:00
sfxKill3DSound ( actor , - 1 , - 1 ) ;
2021-08-27 07:44:47 +00:00
evKillActor ( actor ) ;
2020-12-05 11:17:28 +00:00
2021-08-23 17:21:41 +00:00
int nType = kExplosionStandard ;
2020-05-22 16:28:03 +00:00
2021-08-23 17:21:41 +00:00
switch ( pSprite - > type )
{
case kMissileFireballNapalm :
nType = kExplosionNapalm ;
2020-12-05 11:17:28 +00:00
seqSpawn ( 4 , actor , - 1 ) ;
2021-12-18 15:02:15 +00:00
if ( Chance ( 0x8000 ) ) pSprite - > cstat | = CSTAT_SPRITE_XFLIP ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 303 , - 1 , 0 ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_5 , nullptr , nullptr ) ;
2021-08-23 17:21:41 +00:00
break ;
2020-12-05 11:17:28 +00:00
2021-08-23 17:21:41 +00:00
case kMissileFlareAlt :
nType = kExplosionFireball ;
2020-12-05 11:17:28 +00:00
seqSpawn ( 9 , actor , - 1 ) ;
2021-12-18 15:02:15 +00:00
if ( Chance ( 0x8000 ) ) pSprite - > cstat | = CSTAT_SPRITE_XFLIP ;
2021-11-10 23:32:15 +00:00
sfxPlay3DSound ( actor , 306 , 24 + ( actor - > GetIndex ( ) & 3 ) , FX_GlobalChannel ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_5 , nullptr , nullptr ) ;
2021-08-23 17:21:41 +00:00
break ;
2020-12-05 11:17:28 +00:00
2021-08-23 17:21:41 +00:00
case kMissileFireballCerberus :
case kMissileFireballTchernobog :
nType = kExplosionFireball ;
2020-12-05 11:17:28 +00:00
seqSpawn ( 5 , actor , - 1 ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 304 , - 1 , 0 ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_5 , nullptr , nullptr ) ;
2021-08-23 17:21:41 +00:00
break ;
2020-12-05 11:17:28 +00:00
2021-08-23 17:21:41 +00:00
case kThingArmedTNTStick :
nType = kExplosionSmall ;
2021-08-29 17:09:29 +00:00
if ( actor - > hit . florhit . type = = kHitNone ) seqSpawn ( 4 , actor , - 1 ) ;
2020-12-05 11:17:28 +00:00
else seqSpawn ( 3 , actor , - 1 ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 303 , - 1 , 0 ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_5 , nullptr , nullptr ) ;
2021-08-23 17:21:41 +00:00
break ;
2020-12-05 11:17:28 +00:00
2021-08-23 17:21:41 +00:00
case kThingArmedProxBomb :
case kThingArmedRemoteBomb :
case kThingArmedTNTBundle :
2020-12-05 11:17:28 +00:00
# ifdef NOONE_EXTENSIONS
2021-08-23 17:21:41 +00:00
case kModernThingTNTProx :
2020-12-05 11:17:28 +00:00
# endif
2021-08-23 17:21:41 +00:00
nType = kExplosionStandard ;
2021-08-29 17:09:29 +00:00
if ( actor - > hit . florhit . type = = kHitNone ) seqSpawn ( 4 , actor , - 1 ) ;
2021-08-23 17:21:41 +00:00
else
2020-12-05 11:17:28 +00:00
seqSpawn ( 3 , actor , - 1 ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 304 , - 1 , 0 ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_5 , nullptr , nullptr ) ;
2021-08-23 17:21:41 +00:00
break ;
2020-12-05 11:17:28 +00:00
2021-08-23 17:21:41 +00:00
case kThingArmedSpray :
nType = kExplosionSpray ;
2020-12-05 11:17:28 +00:00
seqSpawn ( 5 , actor , - 1 ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 307 , - 1 , 0 ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_5 , nullptr , nullptr ) ;
2021-08-23 17:21:41 +00:00
break ;
2020-12-05 11:17:28 +00:00
2021-08-23 17:21:41 +00:00
case kThingTNTBarrel :
{
2021-11-23 23:55:57 +00:00
auto spawned = actSpawnSprite ( pSprite - > sector ( ) , pSprite - > x , pSprite - > y , pSprite - > z , 0 , 1 ) ;
2020-12-05 11:17:28 +00:00
spawned - > SetOwner ( actor - > GetOwner ( ) ) ;
2021-08-30 18:21:49 +00:00
if ( actCheckRespawn ( actor ) )
2021-08-23 17:21:41 +00:00
{
pXSprite - > state = 1 ;
2020-12-05 11:17:28 +00:00
pXSprite - > health = thingInfo [ 0 ] . startHealth < < 4 ;
2021-08-23 17:21:41 +00:00
}
2020-12-05 11:17:28 +00:00
else actPostSprite ( actor , kStatFree ) ;
2021-08-23 17:21:41 +00:00
nType = kExplosionLarge ;
2020-12-05 11:17:28 +00:00
seqSpawn ( 4 , spawned , - 1 ) ;
actor = spawned ;
pSprite = & spawned - > s ( ) ;
pXSprite = & spawned - > x ( ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 305 , - 1 , 0 ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_14 , nullptr , nullptr ) ;
2021-08-23 17:21:41 +00:00
break ;
}
2020-12-05 11:17:28 +00:00
case kTrapExploder :
2019-09-19 22:42:45 +00:00
{
// Defaults for exploder
2020-12-05 11:17:28 +00:00
nType = 1 ;
int nSnd = 304 ;
int nSeq = 4 ;
2019-09-19 22:42:45 +00:00
2020-12-05 11:17:28 +00:00
# ifdef NOONE_EXTENSIONS
2021-08-23 17:21:41 +00:00
// allow to customize hidden exploder trap
2020-12-05 11:17:28 +00:00
if ( gModernMap )
{
nType = pXSprite - > data1 ; // Explosion type
int tSeq = pXSprite - > data2 ; // SEQ id
int tSnd = pXSprite - > data3 ; // Sound Id
2019-10-20 14:50:47 +00:00
2021-08-23 17:21:41 +00:00
if ( nType < = 1 | | nType > kExplodeMax ) { nType = 1 ; nSeq = 4 ; nSnd = 304 ; }
else if ( nType = = 2 ) { nSeq = 4 ; nSnd = 305 ; }
else if ( nType = = 3 ) { nSeq = 9 ; nSnd = 307 ; }
else if ( nType = = 4 ) { nSeq = 5 ; nSnd = 307 ; }
else if ( nType < = 6 ) { nSeq = 4 ; nSnd = 303 ; }
else if ( nType = = 7 ) { nSeq = 4 ; nSnd = 303 ; }
else if ( nType = = 8 ) { nType = 0 ; nSeq = 3 ; nSnd = 303 ; }
// Override previous sound and seq assigns
if ( tSeq > 0 ) nSeq = tSeq ;
if ( tSnd > 0 ) nSnd = tSnd ;
}
2020-12-05 11:17:28 +00:00
# endif
2019-09-19 22:42:45 +00:00
2020-12-05 11:17:28 +00:00
if ( getSequence ( nSeq ) ) seqSpawn ( nSeq , actor , - 1 ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , nSnd , - 1 , 0 ) ;
2020-12-05 11:17:28 +00:00
break ;
2019-09-19 22:42:45 +00:00
}
2021-08-23 17:21:41 +00:00
case kThingPodFireBall :
nType = kExplosionFireball ;
2020-12-05 11:17:28 +00:00
seqSpawn ( 9 , actor , - 1 ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 307 , - 1 , 0 ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_5 , nullptr , nullptr ) ;
2021-08-26 22:07:33 +00:00
fxSpawnPodStuff ( actor , 240 ) ;
2021-08-23 17:21:41 +00:00
break ;
2020-12-05 11:17:28 +00:00
2021-08-23 17:21:41 +00:00
default :
nType = kExplosionStandard ;
2020-12-05 11:17:28 +00:00
seqSpawn ( 4 , actor , - 1 ) ;
2021-12-18 15:02:15 +00:00
if ( Chance ( 0x8000 ) ) pSprite - > cstat | = CSTAT_SPRITE_XFLIP ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 303 , - 1 , 0 ) ;
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_5 , nullptr , nullptr ) ;
2021-08-23 17:21:41 +00:00
break ;
}
2021-09-04 10:52:02 +00:00
actor - > xvel = actor - > yvel = actor - > zvel = 0 ;
2020-12-05 11:17:28 +00:00
actPostSprite ( actor , kStatExplosion ) ;
2021-08-23 17:21:41 +00:00
pSprite - > xrepeat = pSprite - > yrepeat = explodeInfo [ nType ] . repeat ;
2019-10-20 14:50:47 +00:00
2021-08-23 17:21:41 +00:00
pSprite - > flags & = ~ 3 ;
pSprite - > type = nType ;
2020-12-05 11:17:28 +00:00
const EXPLOSION * pExplodeInfo = & explodeInfo [ nType ] ;
2021-08-29 12:36:40 +00:00
actor - > SetTarget ( nullptr ) ;
2021-08-29 12:42:05 +00:00
actor - > explosionhackflag = true ;
2020-12-05 11:17:28 +00:00
pXSprite - > data1 = pExplodeInfo - > ticks ;
pXSprite - > data2 = pExplodeInfo - > quakeEffect ;
pXSprite - > data3 = pExplodeInfo - > flashEffect ;
2019-09-19 22:42:45 +00:00
}
2020-12-05 11:17:28 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-11-06 21:48:22 +00:00
void actActivateGibObject ( DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2021-08-23 17:21:41 +00:00
auto pXSprite = & actor - > x ( ) ;
auto pSprite = & actor - > s ( ) ;
2019-09-19 22:42:45 +00:00
2020-12-05 11:17:28 +00:00
int gib1 = ClipRange ( pXSprite - > data1 , 0 , 31 ) ;
int gib2 = ClipRange ( pXSprite - > data2 , 0 , 31 ) ;
int gib3 = ClipRange ( pXSprite - > data3 , 0 , 31 ) ;
int sound = pXSprite - > data4 ;
int dropmsg = pXSprite - > dropMsg ;
2021-08-29 20:22:16 +00:00
if ( gib1 > 0 ) GibSprite ( actor , ( GIBTYPE ) ( gib1 - 1 ) , nullptr , nullptr ) ;
if ( gib2 > 0 ) GibSprite ( actor , ( GIBTYPE ) ( gib2 - 1 ) , nullptr , nullptr ) ;
if ( gib3 > 0 & & pXSprite - > burnTime > 0 ) GibSprite ( actor , ( GIBTYPE ) ( gib3 - 1 ) , nullptr , nullptr ) ;
2021-11-23 23:38:07 +00:00
if ( sound > 0 ) sfxPlay3DSound ( pSprite - > x , pSprite - > y , pSprite - > z , sound , pSprite - > sector ( ) ) ;
2020-12-05 22:49:51 +00:00
if ( dropmsg > 0 ) actDropObject ( actor , dropmsg ) ;
2020-12-05 11:17:28 +00:00
2021-12-18 15:09:58 +00:00
if ( ! ( pSprite - > cstat & CSTAT_SPRITE_INVISIBLE ) & & ! ( pSprite - > flags & kHitagRespawn ) )
2020-12-05 11:17:28 +00:00
actPostSprite ( actor , kStatFree ) ;
2019-09-19 22:42:45 +00:00
}
2020-12-05 11:17:28 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-12-05 11:54:26 +00:00
static void actCheckProximity ( )
2019-09-19 22:42:45 +00:00
{
2020-12-05 11:54:26 +00:00
BloodStatIterator it ( kStatThing ) ;
while ( auto actor = it . Next ( ) )
{
spritetype * pSprite = & actor - > s ( ) ;
if ( pSprite - > flags & 32 ) continue ;
2019-09-21 11:02:17 +00:00
2020-12-05 11:54:26 +00:00
if ( actor - > hasX ( ) )
2021-08-25 06:46:31 +00:00
{
2020-12-05 11:54:26 +00:00
XSPRITE * pXSprite = & actor - > x ( ) ;
switch ( pSprite - > type )
{
2021-08-25 06:46:31 +00:00
case kThingBloodBits :
case kThingBloodChunks :
case kThingZombieHead :
if ( pXSprite - > locked & & PlayClock > = pXSprite - > targetX ) pXSprite - > locked = 0 ;
break ;
2021-08-23 17:21:41 +00:00
}
if ( pXSprite - > burnTime > 0 )
{
2020-12-05 11:54:26 +00:00
pXSprite - > burnTime = ClipLow ( pXSprite - > burnTime - 4 , 0 ) ;
2021-09-18 18:12:15 +00:00
actDamageSprite ( actor - > GetBurnSource ( ) , actor , kDamageBurn , 8 ) ;
2021-08-23 17:21:41 +00:00
}
2020-12-05 11:54:26 +00:00
if ( pXSprite - > Proximity )
{
# ifdef NOONE_EXTENSIONS
2021-08-23 17:21:41 +00:00
// don't process locked or 1-shot things for proximity
2020-12-05 11:54:26 +00:00
if ( gModernMap & & ( pXSprite - > locked | | pXSprite - > isTriggered ) )
2021-08-23 17:21:41 +00:00
continue ;
2020-12-05 11:54:26 +00:00
# endif
2021-09-15 22:52:54 +00:00
if ( pSprite - > type = = kThingDroppedLifeLeech ) actor - > SetTarget ( nullptr ) ;
2020-12-05 11:54:26 +00:00
BloodStatIterator it1 ( kStatDude ) ;
while ( auto dudeactor = it1 . Next ( ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 11:54:26 +00:00
auto nextdude = it1 . Peek ( ) ;
spritetype * pSprite2 = & dudeactor - > s ( ) ;
2019-10-20 14:50:47 +00:00
2020-12-05 11:54:26 +00:00
if ( pSprite2 - > flags & 32 | | ! dudeactor - > hasX ( ) ) continue ;
XSPRITE * pXSprite2 = & dudeactor - > x ( ) ;
if ( ( unsigned int ) pXSprite2 - > health > 0 )
{
int proxyDist = 96 ;
# ifdef NOONE_EXTENSIONS
2021-08-23 17:21:41 +00:00
// allow dudeLockout for proximity flag
2020-12-05 11:54:26 +00:00
if ( gModernMap & & pSprite - > type ! = kThingDroppedLifeLeech & & pXSprite - > DudeLockout & & ! dudeactor - > IsPlayerActor ( ) )
2021-08-23 17:21:41 +00:00
continue ;
2019-09-21 11:02:17 +00:00
2021-08-23 17:21:41 +00:00
if ( pSprite - > type = = kModernThingEnemyLifeLeech ) proxyDist = 512 ;
2020-12-05 11:54:26 +00:00
# endif
2021-09-15 22:52:54 +00:00
if ( pSprite - > type = = kThingDroppedLifeLeech & & actor - > GetTarget ( ) = = nullptr )
2020-12-05 11:54:26 +00:00
{
auto Owner = actor - > GetOwner ( ) ;
if ( ! Owner - > IsPlayerActor ( ) ) continue ;
spritetype * pOwner = & Owner - > s ( ) ;
PLAYER * pPlayer = & gPlayer [ pOwner - > type - kDudePlayer1 ] ;
PLAYER * pPlayer2 = dudeactor - > IsPlayerActor ( ) ? & gPlayer [ pSprite2 - > type - kDudePlayer1 ] : nullptr ;
if ( dudeactor = = Owner | | pSprite2 - > type = = kDudeZombieAxeBuried | | pSprite2 - > type = = kDudeRat | | pSprite2 - > type = = kDudeBat ) continue ;
if ( gGameOptions . nGameType = = 3 & & pPlayer2 & & pPlayer - > teamId = = pPlayer2 - > teamId ) continue ;
if ( gGameOptions . nGameType = = 1 & & pPlayer2 ) continue ;
2021-08-23 17:21:41 +00:00
proxyDist = 512 ;
}
2019-09-21 11:02:17 +00:00
2021-11-23 23:52:54 +00:00
if ( CheckProximity ( dudeactor , pSprite - > x , pSprite - > y , pSprite - > z , pSprite - > sector ( ) , proxyDist ) )
2020-12-05 11:54:26 +00:00
{
switch ( pSprite - > type )
{
2021-08-25 06:46:31 +00:00
case kThingDroppedLifeLeech :
2020-12-05 11:54:26 +00:00
if ( ! Chance ( 0x4000 ) & & nextdude ) continue ;
2021-12-18 18:19:28 +00:00
if ( pSprite2 - > cstat & CSTAT_SPRITE_BLOCK ) actor - > SetTarget ( dudeactor ) ;
2021-08-25 06:46:31 +00:00
else continue ;
break ;
2020-12-05 11:54:26 +00:00
# ifdef NOONE_EXTENSIONS
2021-08-25 06:46:31 +00:00
case kModernThingTNTProx :
2020-12-05 11:54:26 +00:00
if ( ! dudeactor - > IsPlayerActor ( ) ) continue ;
2021-08-25 06:46:31 +00:00
pSprite - > pal = 0 ;
break ;
2020-12-05 11:54:26 +00:00
2021-08-25 06:46:31 +00:00
case kModernThingEnemyLifeLeech :
2021-09-15 22:52:54 +00:00
if ( actor - > GetTarget ( ) ! = dudeactor ) continue ;
2021-08-25 06:46:31 +00:00
break ;
2020-12-05 11:54:26 +00:00
# endif
default :
break ;
2021-08-23 17:21:41 +00:00
}
2021-08-29 21:10:19 +00:00
if ( actor - > GetOwner ( ) = = nullptr ) actor - > SetOwner ( dudeactor ) ;
2020-12-05 11:54:26 +00:00
trTriggerSprite ( actor , kCmdSpriteProximity ) ;
2021-08-23 17:21:41 +00:00
}
}
}
}
}
}
2020-12-05 11:54:26 +00:00
}
2020-10-15 15:08:21 +00:00
2020-12-05 11:54:26 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void actCheckThings ( )
{
BloodStatIterator it ( kStatThing ) ;
while ( auto actor = it . Next ( ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 11:54:26 +00:00
spritetype * pSprite = & actor - > s ( ) ;
2019-10-20 14:50:47 +00:00
2020-12-05 11:54:26 +00:00
if ( pSprite - > flags & 32 ) continue ;
if ( ! actor - > hasX ( ) ) continue ;
auto pXSprite = & actor - > x ( ) ;
2021-11-19 16:29:49 +00:00
auto pSector = pSprite - > sector ( ) ;
2020-12-05 11:54:26 +00:00
2021-11-19 16:29:49 +00:00
XSECTOR * pXSector = pSector - > hasX ( ) ? & pSector - > xs ( ) : nullptr ;
2021-08-23 17:21:41 +00:00
if ( pXSector & & pXSector - > panVel & & ( pXSector - > panAlways | | pXSector - > state | | pXSector - > busy ) )
{
int nType = pSprite - > type - kThingBase ;
2020-12-05 11:54:26 +00:00
const THINGINFO * pThingInfo = & thingInfo [ nType ] ;
if ( pThingInfo - > flags & 1 ) pSprite - > flags | = 1 ;
if ( pThingInfo - > flags & 2 ) pSprite - > flags | = 4 ;
2021-08-23 17:21:41 +00:00
}
2019-10-20 14:50:47 +00:00
2020-12-05 11:54:26 +00:00
if ( pSprite - > flags & 3 )
2021-08-23 17:21:41 +00:00
{
2020-12-05 11:54:26 +00:00
viewBackupSpriteLoc ( actor ) ;
2021-08-23 17:21:41 +00:00
if ( pXSector & & pXSector - > panVel )
{
int top , bottom ;
2020-12-05 11:54:26 +00:00
GetActorExtents ( actor , & top , & bottom ) ;
2021-11-19 16:29:49 +00:00
if ( getflorzofslopeptr ( pSector , pSprite - > x , pSprite - > y ) < = bottom )
2021-08-23 17:21:41 +00:00
{
int angle = pXSector - > panAngle ;
int speed = 0 ;
if ( pXSector - > panAlways | | pXSector - > state | | pXSector - > busy )
{
speed = pXSector - > panVel < < 9 ;
2020-12-05 11:54:26 +00:00
if ( ! pXSector - > panAlways & & pXSector - > busy ) speed = MulScale ( speed , pXSector - > busy , 16 ) ;
2021-08-23 17:21:41 +00:00
}
2021-12-18 13:08:57 +00:00
if ( pSector - > floorstat & CSTAT_SECTOR_ALIGN ) angle = ( angle + GetWallAngle ( pSector - > firstWall ( ) ) + 512 ) & 2047 ;
2020-12-05 11:54:26 +00:00
2021-09-04 10:52:02 +00:00
actor - > xvel + = MulScale ( speed , Cos ( angle ) , 30 ) ;
actor - > yvel + = MulScale ( speed , Sin ( angle ) , 30 ) ;
2021-08-23 17:21:41 +00:00
}
}
2020-12-05 11:54:26 +00:00
actAirDrag ( actor , 128 ) ;
2019-10-20 14:50:47 +00:00
2021-11-10 23:32:15 +00:00
if ( ( ( actor - > GetIndex ( ) > > 8 ) & 15 ) = = ( gFrameCount & 15 ) & & ( pSprite - > flags & 2 ) ) pSprite - > flags | = 4 ;
2021-11-20 18:10:02 +00:00
if ( ( pSprite - > flags & 4 ) | | actor - > xvel | | actor - > yvel | | actor - > zvel | | pSprite - > sector ( ) - > velFloor | | pSprite - > sector ( ) - > velCeil )
2021-08-23 17:21:41 +00:00
{
2020-12-05 11:54:26 +00:00
Collision hit = MoveThing ( actor ) ;
if ( hit . type )
2021-08-23 17:21:41 +00:00
{
2020-12-05 11:54:26 +00:00
if ( pXSprite - > Impact ) trTriggerSprite ( actor , kCmdOff ) ;
switch ( pSprite - > type )
2021-08-23 17:21:41 +00:00
{
2021-08-25 06:46:31 +00:00
case kThingDripWater :
case kThingDripBlood :
2021-08-31 23:28:19 +00:00
MakeSplash ( actor ) ;
2021-08-25 06:46:31 +00:00
break ;
2020-12-05 11:54:26 +00:00
# ifdef NOONE_EXTENSIONS
2021-08-25 06:46:31 +00:00
case kModernThingThrowableRock :
2020-12-05 11:54:26 +00:00
seqSpawn ( 24 , actor , - 1 ) ;
2021-08-26 06:16:43 +00:00
if ( hit . type = = kHitSprite )
2021-08-25 06:46:31 +00:00
{
pSprite - > xrepeat = 32 ;
pSprite - > yrepeat = 32 ;
2021-11-26 13:03:21 +00:00
actDamageSprite ( actor - > GetOwner ( ) , hit . actor ( ) , kDamageFall , pXSprite - > data1 ) ;
2021-08-25 06:46:31 +00:00
}
break ;
2020-12-05 11:54:26 +00:00
# endif
2021-08-25 06:46:31 +00:00
case kThingBone :
2020-12-05 11:54:26 +00:00
seqSpawn ( 24 , actor , - 1 ) ;
2021-08-26 06:16:43 +00:00
if ( hit . type = = kHitSprite )
2021-08-25 06:46:31 +00:00
{
2021-11-26 13:03:21 +00:00
actDamageSprite ( actor - > GetOwner ( ) , hit . actor ( ) , kDamageFall , 12 ) ;
2021-08-25 06:46:31 +00:00
}
break ;
2020-12-05 11:54:26 +00:00
2021-08-25 06:46:31 +00:00
case kThingPodGreenBall :
2020-12-05 11:54:26 +00:00
if ( hit . type = = kHitSector )
2021-08-25 06:46:31 +00:00
{
2021-11-23 23:49:29 +00:00
actRadiusDamage ( actor - > GetOwner ( ) , pSprite - > x , pSprite - > y , pSprite - > z , pSprite - > sector ( ) , 200 , 1 , 20 , kDamageExplode , 6 , 0 ) ;
2021-08-27 07:44:47 +00:00
evPostActor ( actor , 0 , kCallbackFXPodBloodSplat ) ;
2021-08-25 06:46:31 +00:00
}
2020-12-05 11:54:26 +00:00
else if ( hit . type = = kHitSprite )
2021-08-25 06:46:31 +00:00
{
2021-11-26 13:03:21 +00:00
actDamageSprite ( actor - > GetOwner ( ) , hit . actor ( ) , kDamageFall , 12 ) ;
2021-08-27 07:44:47 +00:00
evPostActor ( actor , 0 , kCallbackFXPodBloodSplat ) ;
2021-08-25 06:46:31 +00:00
}
break ;
2020-12-05 11:54:26 +00:00
2021-08-25 06:46:31 +00:00
case kThingPodFireBall :
2021-08-27 11:25:01 +00:00
actExplodeSprite ( actor ) ;
2021-08-25 06:46:31 +00:00
break ;
2021-08-23 17:21:41 +00:00
}
}
}
2021-08-25 06:46:31 +00:00
}
}
2020-12-05 11:54:26 +00:00
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-12-05 15:23:01 +00:00
static void actCheckProjectiles ( )
2020-12-05 11:54:26 +00:00
{
BloodStatIterator it ( kStatProjectile ) ;
2020-12-05 15:23:01 +00:00
while ( auto actor = it . Next ( ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 15:23:01 +00:00
spritetype * pSprite = & actor - > s ( ) ;
2019-10-20 14:50:47 +00:00
2021-08-23 17:21:41 +00:00
if ( pSprite - > flags & 32 )
continue ;
2020-12-05 15:23:01 +00:00
viewBackupSpriteLoc ( actor ) ;
int hit = MoveMissile ( actor ) ;
2021-08-31 23:28:19 +00:00
if ( hit > = 0 ) actImpactMissile ( actor , hit ) ;
2021-08-23 17:21:41 +00:00
}
2020-12-05 15:23:01 +00:00
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-11-23 16:10:04 +00:00
static TArray < walltype * > affectedXWalls ; // keep this outside the function so that it only needs to be allocated once
2020-12-05 15:23:01 +00:00
static void actCheckExplosion ( )
{
BloodStatIterator it ( kStatExplosion ) ;
while ( auto actor = it . Next ( ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 15:23:01 +00:00
spritetype * pSprite = & actor - > s ( ) ;
2019-10-20 14:50:47 +00:00
2021-08-23 17:21:41 +00:00
if ( pSprite - > flags & 32 )
continue ;
2020-12-05 15:23:01 +00:00
if ( ! actor - > hasX ( ) ) continue ;
XSPRITE * pXSprite = & actor - > x ( ) ;
auto Owner = actor - > GetOwner ( ) ;
auto pOwner = Owner ? & Owner - > s ( ) : nullptr ;
2021-08-23 17:21:41 +00:00
int nType = pSprite - > type ;
assert ( nType > = 0 & & nType < kExplodeMax ) ;
2020-12-05 15:23:01 +00:00
const EXPLOSION * pExplodeInfo = & explodeInfo [ nType ] ;
2021-08-23 17:21:41 +00:00
int x = pSprite - > x ;
int y = pSprite - > y ;
int z = pSprite - > z ;
2021-11-23 23:47:05 +00:00
auto pSector = pSprite - > sector ( ) ;
2021-08-23 17:21:41 +00:00
int radius = pExplodeInfo - > radius ;
2019-10-11 21:59:39 +00:00
2020-12-05 15:23:01 +00:00
# ifdef NOONE_EXTENSIONS
2021-08-23 17:21:41 +00:00
// Allow to override explosion radius by data4 field of any sprite which have statnum 2 set in editor
// or of Hidden Exploder.
if ( gModernMap & & pXSprite - > data4 > 0 )
radius = pXSprite - > data4 ;
2020-12-05 15:23:01 +00:00
# endif
2021-08-23 17:21:41 +00:00
// GetClosestSpriteSectors() has issues checking some sectors due to optimizations
// the new flag newSectCheckMethod for GetClosestSpriteSectors() does rectify these issues, but this may cause unintended side effects for level scripted explosions
// so only allow this new checking method for dude spawned explosions
2021-11-16 19:20:25 +00:00
affectedXWalls . Clear ( ) ;
2021-08-23 17:24:56 +00:00
const bool newSectCheckMethod = ! cl_bloodvanillaexplosions & & Owner & & Owner - > IsDudeActor ( ) & & ! VanillaMode ( ) ; // use new sector checking logic
2021-11-23 23:47:05 +00:00
auto sectorMap = GetClosestSpriteSectors ( pSector , x , y , radius , & affectedXWalls , newSectCheckMethod ) ;
2021-08-25 06:46:31 +00:00
2021-11-23 16:10:04 +00:00
for ( auto pWall : affectedXWalls )
2021-08-23 17:21:41 +00:00
{
2021-11-23 16:10:04 +00:00
trTriggerWall ( pWall , kCmdWallImpact ) ;
2021-08-23 17:21:41 +00:00
}
2020-12-05 15:23:01 +00:00
BloodStatIterator it1 ( kStatDude ) ;
while ( auto dudeactor = it1 . Next ( ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 15:23:01 +00:00
spritetype * pDude = & dudeactor - > s ( ) ;
if ( pDude - > flags & 32 ) continue ;
2019-10-20 14:50:47 +00:00
2021-11-23 23:04:56 +00:00
if ( CheckSector ( sectorMap , pDude ) )
2021-08-23 17:21:41 +00:00
{
2021-11-23 23:52:54 +00:00
if ( pXSprite - > data1 & & CheckProximity ( dudeactor , x , y , z , pSector , radius ) )
2021-08-23 17:21:41 +00:00
{
2021-08-29 12:42:05 +00:00
if ( pExplodeInfo - > dmg & & actor - > explosionhackflag )
2021-08-23 17:21:41 +00:00
{
2021-08-29 12:42:05 +00:00
actor - > explosionhackflag = false ;
2020-12-05 15:23:01 +00:00
actDamageSprite ( Owner , dudeactor , kDamageFall , ( pExplodeInfo - > dmg + Random ( pExplodeInfo - > dmgRng ) ) < < 4 ) ;
2021-08-23 17:21:41 +00:00
}
2020-12-05 15:23:01 +00:00
if ( pExplodeInfo - > dmgType ) ConcussSprite ( actor , dudeactor , x , y , z , pExplodeInfo - > dmgType ) ;
2021-08-23 17:21:41 +00:00
if ( pExplodeInfo - > burnTime )
{
2020-12-05 15:23:01 +00:00
assert ( dudeactor - > hasX ( ) ) ;
2021-08-17 12:32:32 +00:00
XSPRITE * pXDude = & dudeactor - > x ( ) ;
2021-08-27 07:44:47 +00:00
if ( ! pXDude - > burnTime ) evPostActor ( dudeactor , 0 , kCallbackFXFlameLick ) ;
2020-12-05 15:23:01 +00:00
actBurnSprite ( Owner , dudeactor , pExplodeInfo - > burnTime < < 2 ) ;
2021-08-23 17:21:41 +00:00
}
}
}
}
2020-12-05 15:23:01 +00:00
2021-08-23 17:21:41 +00:00
it1 . Reset ( kStatThing ) ;
2020-12-05 15:23:01 +00:00
while ( auto thingactor = it1 . Next ( ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 15:23:01 +00:00
spritetype * pThing = & thingactor - > s ( ) ;
2019-10-20 14:50:47 +00:00
2020-12-05 15:23:01 +00:00
if ( pThing - > flags & 32 ) continue ;
2021-11-23 23:04:56 +00:00
if ( CheckSector ( sectorMap , pThing ) )
2021-08-23 17:21:41 +00:00
{
2021-11-23 23:52:54 +00:00
if ( pXSprite - > data1 & & CheckProximity ( thingactor , x , y , z , pSector , radius ) & & thingactor - > hasX ( ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 15:23:01 +00:00
XSPRITE * pXThing = & thingactor - > x ( ) ;
if ( ! pXThing - > locked )
2021-08-23 17:21:41 +00:00
{
2020-12-05 15:23:01 +00:00
if ( pExplodeInfo - > dmgType ) ConcussSprite ( Owner , thingactor , x , y , z , pExplodeInfo - > dmgType ) ;
2021-08-23 17:21:41 +00:00
if ( pExplodeInfo - > burnTime )
{
if ( pThing - > type = = kThingTNTBarrel & & ! pXThing - > burnTime )
2021-08-27 07:44:47 +00:00
evPostActor ( thingactor , 0 , kCallbackFXFlameLick ) ;
2020-12-05 15:23:01 +00:00
actBurnSprite ( Owner , thingactor , pExplodeInfo - > burnTime < < 2 ) ;
2021-08-23 17:21:41 +00:00
}
}
}
}
}
for ( int p = connecthead ; p > = 0 ; p = connectpoint2 [ p ] )
{
2020-12-05 15:23:01 +00:00
spritetype * pSprite2 = gPlayer [ p ] . pSprite ;
int dx = ( x - pSprite2 - > x ) > > 4 ;
int dy = ( y - pSprite2 - > y ) > > 4 ;
int dz = ( z - pSprite2 - > z ) > > 8 ;
int nDist = dx * dx + dy * dy + dz * dz + 0x40000 ;
2021-08-23 17:21:41 +00:00
int t = DivScale ( pXSprite - > data2 , nDist , 16 ) ;
gPlayer [ p ] . flickerEffect + = t ;
}
2020-03-01 20:36:28 +00:00
2020-12-05 15:23:01 +00:00
# ifdef NOONE_EXTENSIONS
if ( pXSprite - > data1 ! = 0 )
{
2021-08-25 06:46:31 +00:00
// add impulse for sprites from physics list
2020-12-05 15:23:01 +00:00
if ( gPhysSpritesCount > 0 & & pExplodeInfo - > dmgType ! = 0 )
{
for ( int i = 0 ; i < gPhysSpritesCount ; i + + )
{
2021-09-01 19:52:00 +00:00
if ( gPhysSpritesList [ i ] = = nullptr ) continue ;
2021-12-05 23:20:46 +00:00
DBloodActor * physactor = gPhysSpritesList [ i ] ;
2020-12-05 15:23:01 +00:00
spritetype * pDebris = & physactor - > s ( ) ;
2021-11-24 00:59:55 +00:00
if ( ! pDebris - > insector ( ) | | ( pDebris - > flags & kHitagFree ) ! = 0 ) continue ;
2019-09-21 11:02:17 +00:00
2021-11-23 23:52:54 +00:00
if ( ! CheckSector ( sectorMap , pDebris ) | | ! CheckProximity ( physactor , x , y , z , pSector , radius ) ) continue ;
2021-10-12 22:46:21 +00:00
else debrisConcuss ( Owner , i , x , y , z , pExplodeInfo - > dmgType ) ;
2021-08-25 06:46:31 +00:00
}
2021-08-23 17:21:41 +00:00
}
2020-03-01 20:36:28 +00:00
2021-08-23 17:21:41 +00:00
// trigger sprites from impact list
if ( gImpactSpritesCount > 0 ) {
2020-12-05 15:23:01 +00:00
for ( int i = 0 ; i < gImpactSpritesCount ; i + + )
{
2021-09-01 19:52:00 +00:00
if ( gImpactSpritesList [ i ] = = nullptr ) continue ;
2021-08-30 18:32:14 +00:00
2021-12-05 22:56:35 +00:00
DBloodActor * impactactor = gImpactSpritesList [ i ] ;
2021-12-21 22:18:23 +00:00
if ( ! impactactor - > hasX ( ) | | ! impactactor - > spr . insector ( ) | | ( impactactor - > spr . flags & kHitagFree ) ! = 0 ) continue ;
2020-03-01 20:36:28 +00:00
2021-11-23 23:52:54 +00:00
if ( ! CheckSector ( sectorMap , & impactactor - > s ( ) ) | | ! CheckProximity ( impactactor , x , y , z , pSector , radius ) )
2021-08-23 17:21:41 +00:00
continue ;
2020-12-05 15:23:01 +00:00
2021-08-30 18:32:14 +00:00
trTriggerSprite ( impactactor , kCmdSpriteImpact ) ;
2021-08-25 06:46:31 +00:00
}
2021-08-23 17:21:41 +00:00
}
2020-03-01 20:36:28 +00:00
2021-08-23 17:21:41 +00:00
}
2020-12-05 15:23:01 +00:00
if ( ! gModernMap | | ! ( pSprite - > flags & kModernTypeFlag1 ) )
{
// if data4 > 0, do not remove explosion. This can be useful when designer wants put explosion generator in map manually via sprite statnum 2.
2021-08-23 17:21:41 +00:00
pXSprite - > data1 = ClipLow ( pXSprite - > data1 - 4 , 0 ) ;
pXSprite - > data2 = ClipLow ( pXSprite - > data2 - 4 , 0 ) ;
pXSprite - > data3 = ClipLow ( pXSprite - > data3 - 4 , 0 ) ;
}
2020-12-05 15:23:01 +00:00
# else
2021-08-23 17:21:41 +00:00
pXSprite - > data1 = ClipLow ( pXSprite - > data1 - 4 , 0 ) ;
pXSprite - > data2 = ClipLow ( pXSprite - > data2 - 4 , 0 ) ;
pXSprite - > data3 = ClipLow ( pXSprite - > data3 - 4 , 0 ) ;
2020-12-05 15:23:01 +00:00
# endif
2019-09-19 22:42:45 +00:00
2020-12-05 15:23:01 +00:00
if ( pXSprite - > data1 = = 0 & & pXSprite - > data2 = = 0 & & pXSprite - > data3 = = 0 & & seqGetStatus ( actor ) < 0 )
actPostSprite ( actor , kStatFree ) ;
2021-08-23 17:21:41 +00:00
}
2020-12-05 15:23:01 +00:00
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void actCheckTraps ( )
{
BloodStatIterator it ( kStatTraps ) ;
while ( auto actor = it . Next ( ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 15:23:01 +00:00
spritetype * pSprite = & actor - > s ( ) ;
2019-10-20 14:50:47 +00:00
2020-12-05 15:23:01 +00:00
if ( ( pSprite - > flags & 32 ) | | ! actor - > hasX ( ) )
2021-08-23 17:21:41 +00:00
continue ;
2020-12-05 15:23:01 +00:00
XSPRITE * pXSprite = & actor - > x ( ) ;
2021-08-23 17:21:41 +00:00
switch ( pSprite - > type ) {
case kTrapSawCircular :
2020-12-05 15:23:01 +00:00
pXSprite - > data2 = ClipLow ( pXSprite - > data2 - 4 , 0 ) ;
2021-08-23 17:21:41 +00:00
break ;
2020-12-05 15:23:01 +00:00
2021-08-23 17:21:41 +00:00
case kTrapFlame :
2020-12-05 15:23:01 +00:00
if ( pXSprite - > state & & seqGetStatus ( actor ) < 0 )
{
2021-08-23 17:21:41 +00:00
int x = pSprite - > x ;
int y = pSprite - > y ;
int z = pSprite - > z ;
2020-12-05 15:23:01 +00:00
int t = ( pXSprite - > data1 < < 23 ) / 120 ;
2021-08-23 17:21:41 +00:00
int dx = MulScale ( t , Cos ( pSprite - > ang ) , 30 ) ;
int dy = MulScale ( t , Sin ( pSprite - > ang ) , 30 ) ;
for ( int i = 0 ; i < 2 ; i + + )
{
2021-11-23 23:41:19 +00:00
auto pFX = gFX . fxSpawnActor ( FX_32 , pSprite - > sector ( ) , x , y , z , 0 ) ;
2021-08-23 17:21:41 +00:00
if ( pFX )
{
2021-09-04 10:52:02 +00:00
pFX - > xvel = dx + Random2 ( 0x8888 ) ;
pFX - > yvel = dy + Random2 ( 0x8888 ) ;
pFX - > zvel = Random2 ( 0x8888 ) ;
2021-08-23 17:21:41 +00:00
}
2020-12-05 15:23:01 +00:00
x + = ( dx / 2 ) > > 12 ;
y + = ( dy / 2 ) > > 12 ;
2021-08-23 17:21:41 +00:00
}
2021-10-30 06:22:17 +00:00
dy = bsin ( pSprite - > ang ) ;
2021-10-30 06:22:27 +00:00
dx = bcos ( pSprite - > ang ) ;
2020-12-05 15:23:01 +00:00
gVectorData [ kVectorTchernobogBurn ] . maxDist = pXSprite - > data1 < < 9 ;
2021-08-30 18:28:24 +00:00
actFireVector ( actor , 0 , 0 , dx , dy , Random2 ( 0x8888 ) , kVectorTchernobogBurn ) ;
2021-08-23 17:21:41 +00:00
}
break ;
}
}
2020-12-05 15:23:01 +00:00
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void actCheckDudes ( )
{
BloodStatIterator it ( kStatDude ) ;
while ( auto actor = it . Next ( ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 15:23:01 +00:00
spritetype * pSprite = & actor - > s ( ) ;
2019-10-20 14:50:47 +00:00
2021-08-23 17:21:41 +00:00
if ( pSprite - > flags & 32 )
continue ;
2020-12-05 15:23:01 +00:00
if ( actor - > hasX ( ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 15:23:01 +00:00
XSPRITE * pXSprite = & actor - > x ( ) ;
2021-08-29 11:44:04 +00:00
const bool fixBurnGlitch = ! cl_bloodvanillaenemies & & IsBurningDude ( actor ) & & ! VanillaMode ( ) ; // if enemies are burning, always apply burning damage per tick
2021-08-23 17:21:41 +00:00
if ( ( pXSprite - > burnTime > 0 ) | | fixBurnGlitch )
{
switch ( pSprite - > type )
{
case kDudeBurningInnocent :
case kDudeBurningCultist :
case kDudeBurningZombieAxe :
case kDudeBurningZombieButcher :
2020-12-05 15:23:01 +00:00
actDamageSprite ( actor - > GetBurnSource ( ) , actor , kDamageBurn , 8 ) ;
2021-08-23 17:21:41 +00:00
break ;
2020-12-05 15:23:01 +00:00
2021-08-23 17:21:41 +00:00
default :
2020-12-05 15:23:01 +00:00
pXSprite - > burnTime = ClipLow ( pXSprite - > burnTime - 4 , 0 ) ;
actDamageSprite ( actor - > GetBurnSource ( ) , actor , kDamageBurn , 8 ) ;
2021-08-23 17:21:41 +00:00
break ;
}
}
2019-09-19 22:42:45 +00:00
2020-12-05 15:23:01 +00:00
# ifdef NOONE_EXTENSIONS
2021-08-23 17:21:41 +00:00
// handle incarnations of custom dude
2020-12-05 15:23:01 +00:00
if ( pSprite - > type = = kDudeModernCustom & & pXSprite - > txID > 0 & & pXSprite - > sysData1 = = kGenDudeTransformStatus )
{
2021-09-04 10:52:02 +00:00
actor - > xvel = actor - > yvel = 0 ;
2021-05-06 07:55:56 +00:00
if ( seqGetStatus ( actor ) < 0 ) genDudeTransform ( actor ) ;
2021-08-25 06:46:31 +00:00
}
2020-12-05 15:23:01 +00:00
# endif
2021-08-23 17:21:41 +00:00
if ( pSprite - > type = = kDudeCerberusTwoHead )
{
2020-12-05 15:23:01 +00:00
if ( pXSprite - > health < = 0 & & seqGetStatus ( actor ) < 0 )
2021-08-23 17:21:41 +00:00
{
2020-12-05 15:23:01 +00:00
pXSprite - > health = dudeInfo [ 28 ] . startHealth < < 4 ;
2021-08-23 17:21:41 +00:00
pSprite - > type = kDudeCerberusOneHead ;
2021-09-15 22:52:54 +00:00
if ( actor - > GetTarget ( ) ! = nullptr ) aiSetTarget ( actor , actor - > GetTarget ( ) ) ;
2020-12-05 15:23:01 +00:00
aiActivateDude ( actor ) ;
2021-08-23 17:21:41 +00:00
}
}
if ( pXSprite - > Proximity & & ! pXSprite - > isTriggered )
{
2020-12-05 15:23:01 +00:00
BloodStatIterator it1 ( kStatDude ) ;
while ( auto actor2 = it1 . Next ( ) )
2021-08-23 17:21:41 +00:00
{
2021-10-23 22:06:02 +00:00
spritetype * pSprite2 = & actor2 - > s ( ) ;
2020-12-05 15:23:01 +00:00
if ( pSprite2 - > flags & 32 ) continue ;
2019-10-20 14:50:47 +00:00
2021-10-23 22:06:02 +00:00
XSPRITE * pXSprite2 = & actor2 - > x ( ) ;
2020-12-05 15:23:01 +00:00
2021-09-04 18:01:28 +00:00
if ( ( unsigned int ) pXSprite2 - > health > 0 & & actor2 - > IsPlayerActor ( ) )
2020-12-05 15:23:01 +00:00
{
2021-11-23 23:52:54 +00:00
if ( CheckProximity ( actor2 , pSprite - > x , pSprite - > y , pSprite - > z , pSprite - > sector ( ) , 128 ) )
2020-12-05 15:23:01 +00:00
trTriggerSprite ( actor , kCmdSpriteProximity ) ;
2021-08-23 17:21:41 +00:00
}
}
}
2020-12-05 15:23:01 +00:00
if ( actor - > IsPlayerActor ( ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 15:23:01 +00:00
PLAYER * pPlayer = & gPlayer [ pSprite - > type - kDudePlayer1 ] ;
if ( pPlayer - > voodooTargets ) voodooTarget ( pPlayer ) ;
if ( pPlayer - > hand & & Chance ( 0x8000 ) ) actDamageSprite ( actor , actor , kDamageDrown , 12 ) ;
2021-08-23 17:21:41 +00:00
if ( pPlayer - > isUnderwater )
{
2021-11-16 17:30:23 +00:00
bool bActive = packItemActive ( pPlayer , 1 ) ;
2020-12-05 15:23:01 +00:00
if ( bActive | | pPlayer - > godMode ) pPlayer - > underwaterTime = 1200 ;
else pPlayer - > underwaterTime = ClipLow ( pPlayer - > underwaterTime - 4 , 0 ) ;
2021-08-23 17:21:41 +00:00
if ( pPlayer - > underwaterTime < 1080 & & packCheckItem ( pPlayer , 1 ) & & ! bActive )
packUseItem ( pPlayer , 1 ) ;
2020-12-05 15:23:01 +00:00
2021-08-23 17:21:41 +00:00
if ( ! pPlayer - > underwaterTime )
{
pPlayer - > chokeEffect + = 4 ;
if ( Chance ( pPlayer - > chokeEffect ) )
2020-12-05 15:23:01 +00:00
actDamageSprite ( actor , actor , kDamageDrown , 3 < < 4 ) ;
2021-08-23 17:21:41 +00:00
}
else
pPlayer - > chokeEffect = 0 ;
2020-12-05 15:23:01 +00:00
2021-09-04 10:52:02 +00:00
if ( actor - > xvel | | actor - > yvel )
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 709 , 100 , 2 ) ;
2020-12-05 15:23:01 +00:00
pPlayer - > bubbleTime = ClipLow ( pPlayer - > bubbleTime - 4 , 0 ) ;
2021-08-23 17:21:41 +00:00
}
else if ( gGameOptions . nGameType = = 0 )
{
if ( pPlayer - > pXSprite - > health > 0 & & pPlayer - > restTime > = 1200 & & Chance ( 0x200 ) )
{
pPlayer - > restTime = - 1 ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 3100 + Random ( 11 ) , 0 , 2 ) ;
2021-08-23 17:21:41 +00:00
}
}
}
2020-12-05 15:23:01 +00:00
ProcessTouchObjects ( actor ) ;
2021-08-23 17:21:41 +00:00
}
}
2020-12-05 15:23:01 +00:00
2021-08-23 17:21:41 +00:00
it . Reset ( kStatDude ) ;
2020-12-05 15:23:01 +00:00
while ( auto actor = it . Next ( ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 15:23:01 +00:00
spritetype * pSprite = & actor - > s ( ) ;
if ( pSprite - > flags & 32 | | ! actor - > hasX ( ) ) continue ;
2019-10-20 14:50:47 +00:00
2021-11-19 16:29:49 +00:00
auto pSector = pSprite - > sector ( ) ;
2020-12-05 15:23:01 +00:00
viewBackupSpriteLoc ( actor ) ;
2021-11-19 16:29:49 +00:00
XSECTOR * pXSector = pSector - > hasX ( ) ? & pSector - > xs ( ) : nullptr ;
2020-12-05 15:23:01 +00:00
2021-08-23 17:21:41 +00:00
if ( pXSector )
{
int top , bottom ;
2020-12-05 15:23:01 +00:00
GetActorExtents ( actor , & top , & bottom ) ;
2021-11-19 16:29:49 +00:00
if ( getflorzofslopeptr ( pSector , pSprite - > x , pSprite - > y ) < = bottom )
2021-08-23 17:21:41 +00:00
{
int angle = pXSector - > panAngle ;
int speed = 0 ;
if ( pXSector - > panAlways | | pXSector - > state | | pXSector - > busy )
{
speed = pXSector - > panVel < < 9 ;
if ( ! pXSector - > panAlways & & pXSector - > busy )
speed = MulScale ( speed , pXSector - > busy , 16 ) ;
}
2021-12-18 13:08:57 +00:00
if ( pSector - > floorstat & CSTAT_SECTOR_ALIGN )
2021-11-21 08:45:50 +00:00
angle = ( angle + GetWallAngle ( pSector - > firstWall ( ) ) + 512 ) & 2047 ;
2021-08-23 17:21:41 +00:00
int dx = MulScale ( speed , Cos ( angle ) , 30 ) ;
int dy = MulScale ( speed , Sin ( angle ) , 30 ) ;
2021-09-04 10:52:02 +00:00
actor - > xvel + = dx ;
actor - > yvel + = dy ;
2021-08-23 17:21:41 +00:00
}
}
2020-12-05 15:23:01 +00:00
if ( pXSector & & pXSector - > Underwater ) actAirDrag ( actor , 5376 ) ;
else actAirDrag ( actor , 128 ) ;
2019-10-20 14:50:47 +00:00
2021-11-20 18:10:02 +00:00
if ( ( pSprite - > flags & 4 ) | | actor - > xvel | | actor - > yvel | | actor - > zvel | | pSprite - > sector ( ) - > velFloor | | pSprite - > sector ( ) - > velCeil )
2020-12-05 15:23:01 +00:00
MoveDude ( actor ) ;
2021-08-23 17:21:41 +00:00
}
2020-12-05 15:23:01 +00:00
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void actCheckFlares ( )
{
BloodStatIterator it ( kStatFlare ) ;
while ( auto actor = it . Next ( ) )
2021-08-23 17:21:41 +00:00
{
2020-12-05 15:23:01 +00:00
spritetype * pSprite = & actor - > s ( ) ;
if ( ( pSprite - > flags & 32 ) | | ! actor - > hasX ( ) ) continue ;
2019-10-20 14:50:47 +00:00
2020-12-05 15:23:01 +00:00
XSPRITE * pXSprite = & actor - > x ( ) ;
auto target = actor - > GetTarget ( ) ;
if ( ! target ) continue ;
viewBackupSpriteLoc ( actor ) ;
spritetype * pTarget = & target - > s ( ) ;
2021-08-25 06:46:31 +00:00
auto pXTarget = target - > hasX ( ) ? & target - > x ( ) : nullptr ;
2021-08-23 17:21:41 +00:00
if ( pTarget - > statnum = = kMaxStatus )
{
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_17 , NULL , NULL ) ;
2020-12-05 15:23:01 +00:00
actPostSprite ( actor , kStatFree ) ;
2021-08-23 17:21:41 +00:00
}
2021-08-17 12:32:32 +00:00
if ( pXTarget & & pXTarget - > health > 0 )
2021-08-23 17:21:41 +00:00
{
2020-12-05 15:23:01 +00:00
int x = pTarget - > x + mulscale30r ( Cos ( pXSprite - > goalAng + pTarget - > ang ) , pTarget - > clipdist * 2 ) ;
int y = pTarget - > y + mulscale30r ( Sin ( pXSprite - > goalAng + pTarget - > ang ) , pTarget - > clipdist * 2 ) ;
int z = pTarget - > z + pXSprite - > targetZ ;
2021-08-23 17:21:41 +00:00
vec3_t pos = { x , y , z } ;
2021-11-26 20:52:01 +00:00
SetActor ( actor , & pos ) ;
2021-09-04 10:52:02 +00:00
actor - > xvel = target - > xvel ;
actor - > yvel = target - > yvel ;
actor - > zvel = target - > zvel ;
2021-08-23 17:21:41 +00:00
}
else
{
2021-08-29 20:22:16 +00:00
GibSprite ( actor , GIBTYPE_17 , NULL , NULL ) ;
2020-12-05 15:23:01 +00:00
actPostSprite ( actor , kStatFree ) ;
2021-08-23 17:21:41 +00:00
}
}
2020-12-05 15:23:01 +00:00
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void actProcessSprites ( void )
{
# ifdef NOONE_EXTENSIONS
if ( gModernMap ) nnExtProcessSuperSprites ( ) ;
# endif
actCheckProximity ( ) ;
actCheckThings ( ) ;
actCheckProjectiles ( ) ;
actCheckExplosion ( ) ;
actCheckTraps ( ) ;
actCheckDudes ( ) ;
actCheckFlares ( ) ;
2021-08-25 06:46:31 +00:00
aiProcessDudes ( ) ;
gFX . fxProcess ( ) ;
2019-09-19 22:42:45 +00:00
}
2020-12-05 15:23:01 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-11-23 23:55:57 +00:00
DBloodActor * actSpawnSprite ( sectortype * pSector , int x , int y , int z , int nStat , bool setextra )
2019-09-19 22:42:45 +00:00
{
2021-11-23 23:55:57 +00:00
DBloodActor * actor = InsertSprite ( pSector , nStat ) ;
2020-12-05 16:24:27 +00:00
2021-08-25 06:46:31 +00:00
vec3_t pos = { x , y , z } ;
2021-11-26 20:52:01 +00:00
SetActor ( actor , & pos ) ;
2020-12-05 16:24:27 +00:00
spritetype * pSprite = & actor - > s ( ) ;
2021-08-25 06:46:31 +00:00
pSprite - > type = kSpriteDecoration ;
2020-12-05 16:24:27 +00:00
if ( setextra & & ! actor - > hasX ( ) )
2021-08-25 06:46:31 +00:00
{
2021-08-27 20:13:17 +00:00
actor - > addX ( ) ;
2021-11-26 13:03:21 +00:00
actor - > hit . florhit . setNone ( ) ;
actor - > hit . ceilhit . setNone ( ) ;
2020-12-05 16:24:27 +00:00
if ( ! VanillaMode ( ) ) actor - > SetTarget ( nullptr ) ;
2021-08-25 06:46:31 +00:00
}
2020-12-05 16:24:27 +00:00
return actor ;
2020-12-02 22:39:38 +00:00
}
2020-12-05 16:24:27 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-09-19 22:42:45 +00:00
2020-12-05 17:32:49 +00:00
DBloodActor * actSpawnSprite ( DBloodActor * source , int nStat )
2019-09-19 22:42:45 +00:00
{
2020-12-05 17:32:49 +00:00
auto pSource = & source - > s ( ) ;
2021-11-23 23:55:57 +00:00
DBloodActor * actor = InsertSprite ( pSource - > sector ( ) , nStat ) ;
2020-12-05 17:32:49 +00:00
spritetype * pSprite = & actor - > s ( ) ;
pSprite - > x = pSource - > x ;
pSprite - > y = pSource - > y ;
pSprite - > z = pSource - > z ;
2021-09-04 10:52:02 +00:00
actor - > xvel = source - > xvel ;
actor - > yvel = source - > yvel ;
actor - > zvel = source - > zvel ;
2020-12-05 17:32:49 +00:00
pSprite - > flags = 0 ;
actor - > addX ( ) ;
2021-11-26 13:03:21 +00:00
actor - > hit . florhit . setNone ( ) ;
actor - > hit . ceilhit . setNone ( ) ;
2020-12-05 17:32:49 +00:00
if ( ! VanillaMode ( ) ) actor - > SetTarget ( nullptr ) ;
return actor ;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-11-16 17:24:01 +00:00
DBloodActor * actSpawnDude ( DBloodActor * source , int nType , int a3 , int a4 )
2020-12-05 17:32:49 +00:00
{
auto pSource = & source - > s ( ) ;
XSPRITE * pXSource = & source - > x ( ) ;
auto spawned = actSpawnSprite ( source , kStatDude ) ;
if ( ! spawned ) return NULL ;
spritetype * pSprite2 = & spawned - > s ( ) ;
XSPRITE * pXSprite2 = & spawned - > x ( ) ;
2021-09-16 19:59:39 +00:00
int angle = pSource - > ang ;
2020-12-05 17:32:49 +00:00
int nDude = nType - kDudeBase ;
2021-09-16 19:59:39 +00:00
int x , y , z ;
z = a4 + pSource - > z ;
if ( a3 < 0 )
{
x = pSource - > x ;
y = pSource - > y ;
}
else
{
2020-12-05 17:32:49 +00:00
x = pSource - > x + mulscale30r ( Cos ( angle ) , a3 ) ;
y = pSource - > y + mulscale30r ( Sin ( angle ) , a3 ) ;
2021-09-16 19:59:39 +00:00
}
pSprite2 - > type = nType ;
pSprite2 - > ang = angle ;
vec3_t pos = { x , y , z } ;
2021-11-26 20:52:01 +00:00
SetActor ( spawned , & pos ) ;
2021-12-18 18:19:28 +00:00
pSprite2 - > cstat | = CSTAT_SPRITE_BLOCK_ALL | CSTAT_SPRITE_BLOOD_BIT1 ;
2020-12-05 17:32:49 +00:00
pSprite2 - > clipdist = getDudeInfo ( nDude + kDudeBase ) - > clipdist ;
pXSprite2 - > health = getDudeInfo ( nDude + kDudeBase ) - > startHealth < < 4 ;
2021-09-16 19:59:39 +00:00
pXSprite2 - > respawn = 1 ;
2020-12-05 17:32:49 +00:00
if ( getSequence ( getDudeInfo ( nDude + kDudeBase ) - > seqStartID ) )
seqSpawn ( getDudeInfo ( nDude + kDudeBase ) - > seqStartID , spawned , - 1 ) ;
# ifdef NOONE_EXTENSIONS
2021-09-16 19:59:39 +00:00
// add a way to inherit some values of spawner type 18 by dude.
// This way designer can count enemies via switches and do many other interesting things.
2020-12-05 17:32:49 +00:00
if ( gModernMap & & pSource - > flags & kModernTypeFlag1 )
{
// allow inheriting only for selected source types
switch ( pSource - > type )
{
2021-09-16 19:59:39 +00:00
case kMarkerDudeSpawn :
//inherit pal?
if ( pSprite2 - > pal < = 0 ) pSprite2 - > pal = pSource - > pal ;
// inherit spawn sprite trigger settings, so designer can count monsters.
pXSprite2 - > txID = pXSource - > txID ;
pXSprite2 - > command = pXSource - > command ;
pXSprite2 - > triggerOn = pXSource - > triggerOn ;
pXSprite2 - > triggerOff = pXSource - > triggerOff ;
// inherit drop items
pXSprite2 - > dropMsg = pXSource - > dropMsg ;
// inherit dude flags
pXSprite2 - > dudeDeaf = pXSource - > dudeDeaf ;
pXSprite2 - > dudeGuard = pXSource - > dudeGuard ;
pXSprite2 - > dudeAmbush = pXSource - > dudeAmbush ;
pXSprite2 - > dudeFlag4 = pXSource - > dudeFlag4 ;
pXSprite2 - > unused1 = pXSource - > unused1 ;
break ;
}
}
2020-12-05 17:32:49 +00:00
# endif
2019-09-19 22:42:45 +00:00
2021-05-05 10:55:52 +00:00
aiInitSprite ( spawned ) ;
2020-12-05 17:32:49 +00:00
return spawned ;
2019-09-19 22:42:45 +00:00
}
2020-12-05 17:32:49 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-09-19 22:42:45 +00:00
2021-11-23 23:58:43 +00:00
DBloodActor * actSpawnThing ( sectortype * pSector , int x , int y , int z , int nThingType )
2019-09-19 22:42:45 +00:00
{
2021-09-16 19:59:39 +00:00
assert ( nThingType > = kThingBase & & nThingType < kThingMax ) ;
2021-11-23 23:58:43 +00:00
auto actor = actSpawnSprite ( pSector , x , y , z , 4 , 1 ) ;
2020-12-05 16:24:27 +00:00
spritetype * pSprite = & actor - > s ( ) ;
2020-12-05 19:22:29 +00:00
int nType = nThingType - kThingBase ;
2021-09-16 19:59:39 +00:00
pSprite - > type = nThingType ;
2021-05-05 15:25:37 +00:00
assert ( actor - > hasX ( ) ) ;
XSPRITE * pXThing = & actor - > x ( ) ;
2020-12-05 19:22:29 +00:00
const THINGINFO * pThingInfo = & thingInfo [ nType ] ;
pXThing - > health = pThingInfo - > startHealth < < 4 ;
2021-09-16 19:59:39 +00:00
pSprite - > clipdist = pThingInfo - > clipdist ;
pSprite - > flags = pThingInfo - > flags ;
2020-12-05 19:22:29 +00:00
if ( pSprite - > flags & 2 ) pSprite - > flags | = 4 ;
2021-09-16 19:59:39 +00:00
pSprite - > cstat | = pThingInfo - > cstat ;
pSprite - > picnum = pThingInfo - > picnum ;
pSprite - > shade = pThingInfo - > shade ;
pSprite - > pal = pThingInfo - > pal ;
2020-12-05 19:22:29 +00:00
if ( pThingInfo - > xrepeat ) pSprite - > xrepeat = pThingInfo - > xrepeat ;
if ( pThingInfo - > yrepeat ) pSprite - > yrepeat = pThingInfo - > yrepeat ;
2021-09-05 10:25:52 +00:00
pSprite - > cstat2 | = CSTAT2_SPRITE_MAPPED ;
2020-12-05 19:22:29 +00:00
switch ( nThingType )
{
2021-09-16 19:59:39 +00:00
case kThingVoodooHead :
pXThing - > data1 = 0 ;
pXThing - > data2 = 0 ;
pXThing - > data3 = 0 ;
pXThing - > data4 = 0 ;
pXThing - > state = 1 ;
pXThing - > triggerOnce = 1 ;
pXThing - > isTriggered = 0 ;
break ;
case kThingDroppedLifeLeech :
2020-12-05 19:22:29 +00:00
# ifdef NOONE_EXTENSIONS
2021-09-16 19:59:39 +00:00
case kModernThingEnemyLifeLeech :
2020-12-05 19:22:29 +00:00
# endif
2021-09-16 19:59:39 +00:00
pXThing - > data1 = 0 ;
pXThing - > data2 = 0 ;
pXThing - > data3 = 0 ;
pXThing - > data4 = 0 ;
pXThing - > state = 1 ;
pXThing - > triggerOnce = 0 ;
pXThing - > isTriggered = 0 ;
break ;
case kThingZombieHead :
pXThing - > data1 = 8 ;
pXThing - > data2 = 0 ;
pXThing - > data3 = 0 ;
pXThing - > data4 = 318 ;
pXThing - > targetX = PlayClock + 180 ;
pXThing - > locked = 1 ;
pXThing - > state = 1 ;
pXThing - > triggerOnce = 0 ;
pXThing - > isTriggered = 0 ;
break ;
case kThingBloodBits :
case kThingBloodChunks :
pXThing - > data1 = ( nThingType = = kThingBloodBits ) ? 19 : 8 ;
pXThing - > data2 = 0 ;
pXThing - > data3 = 0 ;
pXThing - > data4 = 318 ;
pXThing - > targetX = PlayClock + 180 ;
pXThing - > locked = 1 ;
pXThing - > state = 1 ;
pXThing - > triggerOnce = 0 ;
pXThing - > isTriggered = 0 ;
break ;
case kThingArmedTNTStick :
2021-08-27 07:44:47 +00:00
evPostActor ( actor , 0 , kCallbackFXDynPuff ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 450 , 0 , 0 ) ;
2021-09-16 19:59:39 +00:00
break ;
2020-12-05 19:22:29 +00:00
2021-09-16 19:59:39 +00:00
case kThingArmedTNTBundle :
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 450 , 0 , 0 ) ;
2021-08-27 07:44:47 +00:00
evPostActor ( actor , 0 , kCallbackFXDynPuff ) ;
2021-09-16 19:59:39 +00:00
break ;
2020-12-05 19:22:29 +00:00
2021-09-16 19:59:39 +00:00
case kThingArmedSpray :
2021-08-27 07:44:47 +00:00
evPostActor ( actor , 0 , kCallbackFXDynPuff ) ;
2021-09-16 19:59:39 +00:00
break ;
}
2020-12-05 19:22:29 +00:00
return actor ;
2019-09-19 22:42:45 +00:00
}
2020-12-05 19:22:29 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
DBloodActor * actFireThing ( DBloodActor * actor , int a2 , int a3 , int a4 , int thingType , int a6 )
2019-09-19 22:42:45 +00:00
{
2020-12-05 19:22:29 +00:00
auto pSprite = & actor - > s ( ) ;
2021-09-16 19:59:39 +00:00
assert ( thingType > = kThingBase & & thingType < kThingMax ) ;
int x = pSprite - > x + MulScale ( a2 , Cos ( pSprite - > ang + 512 ) , 30 ) ;
int y = pSprite - > y + MulScale ( a2 , Sin ( pSprite - > ang + 512 ) , 30 ) ;
int z = pSprite - > z + a3 ;
x + = MulScale ( pSprite - > clipdist , Cos ( pSprite - > ang ) , 28 ) ;
y + = MulScale ( pSprite - > clipdist , Sin ( pSprite - > ang ) , 28 ) ;
2021-09-04 18:09:56 +00:00
if ( HitScan ( actor , z , x - pSprite - > x , y - pSprite - > y , 0 , CLIPMASK0 , pSprite - > clipdist ) ! = - 1 )
2021-09-16 19:59:39 +00:00
{
2021-12-22 09:36:09 +00:00
x = gHitInfo . hitpos . X - MulScale ( pSprite - > clipdist < < 1 , Cos ( pSprite - > ang ) , 28 ) ;
2021-12-22 09:40:26 +00:00
y = gHitInfo . hitpos . Y - MulScale ( pSprite - > clipdist < < 1 , Sin ( pSprite - > ang ) , 28 ) ;
2021-09-16 19:59:39 +00:00
}
2021-11-23 23:58:43 +00:00
auto fired = actSpawnThing ( pSprite - > sector ( ) , x , y , z , thingType ) ;
2020-12-05 19:22:29 +00:00
spritetype * pThing = & fired - > s ( ) ;
2021-08-29 21:10:19 +00:00
fired - > SetOwner ( actor ) ;
2021-09-16 19:59:39 +00:00
pThing - > ang = pSprite - > ang ;
2021-09-04 10:52:02 +00:00
fired - > xvel = MulScale ( a6 , Cos ( pThing - > ang ) , 30 ) ;
fired - > yvel = MulScale ( a6 , Sin ( pThing - > ang ) , 30 ) ;
fired - > zvel = MulScale ( a6 , a4 , 14 ) ;
fired - > xvel + = actor - > xvel / 2 ;
fired - > yvel + = actor - > yvel / 2 ;
fired - > zvel + = actor - > zvel / 2 ;
2020-12-05 19:22:29 +00:00
return fired ;
2019-09-19 22:42:45 +00:00
}
2020-12-05 19:22:29 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-12-02 21:33:14 +00:00
2020-12-05 20:23:53 +00:00
void actBuildMissile ( DBloodActor * spawned , DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2020-12-05 20:23:53 +00:00
auto pMissile = & spawned - > s ( ) ;
switch ( pMissile - > type )
2021-09-16 19:59:39 +00:00
{
case kMissileLifeLeechRegular :
2021-08-27 07:44:47 +00:00
evPostActor ( spawned , 0 , kCallbackFXFlameLick ) ;
2021-09-16 19:59:39 +00:00
break ;
case kMissileTeslaAlt :
2021-08-27 07:44:47 +00:00
evPostActor ( spawned , 0 , kCallbackFXTeslaAlt ) ;
2021-09-16 19:59:39 +00:00
break ;
case kMissilePukeGreen :
2020-12-05 20:23:53 +00:00
seqSpawn ( 29 , spawned , - 1 ) ;
2021-09-16 19:59:39 +00:00
break ;
case kMissileButcherKnife :
2021-12-18 18:19:28 +00:00
pMissile - > cstat | = CSTAT_SPRITE_ALIGNMENT_WALL ;
2021-09-16 19:59:39 +00:00
break ;
case kMissileTeslaRegular :
2021-11-28 09:24:42 +00:00
sfxPlay3DSound ( spawned , 251 , 0 , 0 ) ;
2021-09-16 19:59:39 +00:00
break ;
case kMissileEctoSkull :
2020-12-05 20:23:53 +00:00
seqSpawn ( 2 , spawned , - 1 ) ;
2021-11-28 09:24:42 +00:00
sfxPlay3DSound ( spawned , 493 , 0 , 0 ) ;
2021-09-16 19:59:39 +00:00
break ;
case kMissileFireballNapalm :
2020-12-05 20:23:53 +00:00
seqSpawn ( 61 , spawned , nNapalmClient ) ;
2021-11-28 09:24:42 +00:00
sfxPlay3DSound ( spawned , 441 , 0 , 0 ) ;
2021-09-16 19:59:39 +00:00
break ;
case kMissileFireball :
2020-12-05 20:23:53 +00:00
seqSpawn ( 22 , spawned , nFireballClient ) ;
2021-11-28 09:24:42 +00:00
sfxPlay3DSound ( spawned , 441 , 0 , 0 ) ;
2021-09-16 19:59:39 +00:00
break ;
case kMissileFlameHound :
2020-12-05 20:23:53 +00:00
seqSpawn ( 27 , spawned , - 1 ) ;
2021-09-04 10:52:02 +00:00
spawned - > xvel + = actor - > xvel / 2 + Random2 ( 0x11111 ) ;
spawned - > yvel + = actor - > yvel / 2 + Random2 ( 0x11111 ) ;
spawned - > zvel + = actor - > zvel / 2 + Random2 ( 0x11111 ) ;
2021-09-16 19:59:39 +00:00
break ;
case kMissileFireballCerberus :
2020-12-05 20:23:53 +00:00
seqSpawn ( 61 , spawned , dword_2192E0 ) ;
2021-11-28 09:24:42 +00:00
sfxPlay3DSound ( spawned , 441 , 0 , 0 ) ;
2021-09-16 19:59:39 +00:00
break ;
case kMissileFireballTchernobog :
2020-12-05 20:23:53 +00:00
seqSpawn ( 23 , spawned , dword_2192D8 ) ;
2021-09-04 10:52:02 +00:00
spawned - > xvel + = actor - > xvel / 2 + Random2 ( 0x11111 ) ;
spawned - > yvel + = actor - > yvel / 2 + Random2 ( 0x11111 ) ;
spawned - > zvel + = actor - > zvel / 2 + Random2 ( 0x11111 ) ;
2021-09-16 19:59:39 +00:00
break ;
case kMissileFlameSpray :
2020-12-05 20:23:53 +00:00
if ( Chance ( 0x8000 ) ) seqSpawn ( 0 , spawned , - 1 ) ;
else seqSpawn ( 1 , spawned , - 1 ) ;
2021-09-04 10:52:02 +00:00
spawned - > xvel + = actor - > xvel / 2 + Random2 ( 0x11111 ) ;
spawned - > yvel + = actor - > yvel / 2 + Random2 ( 0x11111 ) ;
spawned - > zvel + = actor - > zvel / 2 + Random2 ( 0x11111 ) ;
2021-09-16 19:59:39 +00:00
break ;
case kMissileFlareAlt :
2021-08-27 07:44:47 +00:00
evPostActor ( spawned , 30 , kCallbackFXFlareBurst ) ;
evPostActor ( spawned , 0 , kCallbackFXFlareSpark ) ;
2021-11-28 09:24:42 +00:00
sfxPlay3DSound ( spawned , 422 , 0 , 0 ) ;
2021-09-16 19:59:39 +00:00
break ;
case kMissileFlareRegular :
2021-08-27 07:44:47 +00:00
evPostActor ( spawned , 0 , kCallbackFXFlareSpark ) ;
2021-11-28 09:24:42 +00:00
sfxPlay3DSound ( spawned , 422 , 0 , 0 ) ;
2021-09-16 19:59:39 +00:00
break ;
case kMissileLifeLeechAltSmall :
2021-08-27 07:44:47 +00:00
evPostActor ( spawned , 0 , kCallbackFXArcSpark ) ;
2021-09-16 19:59:39 +00:00
break ;
case kMissileArcGargoyle :
2021-11-28 09:24:42 +00:00
sfxPlay3DSound ( spawned , 252 , 0 , 0 ) ;
2021-09-16 19:59:39 +00:00
break ;
}
2019-09-19 22:42:45 +00:00
}
2020-12-05 20:23:53 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
DBloodActor * actFireMissile ( DBloodActor * actor , int a2 , int a3 , int a4 , int a5 , int a6 , int nType )
{
assert ( nType > = kMissileBase & & nType < kMissileMax ) ;
2021-11-16 17:30:23 +00:00
bool impact = false ;
2020-12-05 20:23:53 +00:00
auto pSprite = & actor - > s ( ) ;
const MissileType * pMissileInfo = & missileInfo [ nType - kMissileBase ] ;
int x = pSprite - > x + MulScale ( a2 , Cos ( pSprite - > ang + 512 ) , 30 ) ;
int y = pSprite - > y + MulScale ( a2 , Sin ( pSprite - > ang + 512 ) , 30 ) ;
int z = pSprite - > z + a3 ;
int clipdist = pMissileInfo - > clipDist + pSprite - > clipdist ;
x + = MulScale ( clipdist , Cos ( pSprite - > ang ) , 28 ) ;
y + = MulScale ( clipdist , Sin ( pSprite - > ang ) , 28 ) ;
2021-09-04 18:09:56 +00:00
int hit = HitScan ( actor , z , x - pSprite - > x , y - pSprite - > y , 0 , CLIPMASK0 , clipdist ) ;
2020-12-05 20:23:53 +00:00
if ( hit ! = - 1 )
{
if ( hit = = 3 | | hit = = 0 )
{
2021-11-16 17:30:23 +00:00
impact = true ;
2021-12-22 09:36:09 +00:00
x = gHitInfo . hitpos . X - MulScale ( Cos ( pSprite - > ang ) , 16 , 30 ) ;
2021-12-22 09:40:26 +00:00
y = gHitInfo . hitpos . Y - MulScale ( Sin ( pSprite - > ang ) , 16 , 30 ) ;
2020-12-05 20:23:53 +00:00
}
else
{
2021-12-22 09:36:09 +00:00
x = gHitInfo . hitpos . X - MulScale ( pMissileInfo - > clipDist < < 1 , Cos ( pSprite - > ang ) , 28 ) ;
2021-12-22 09:40:26 +00:00
y = gHitInfo . hitpos . Y - MulScale ( pMissileInfo - > clipDist < < 1 , Sin ( pSprite - > ang ) , 28 ) ;
2020-12-05 20:23:53 +00:00
}
}
2021-11-23 23:55:57 +00:00
auto spawned = actSpawnSprite ( pSprite - > sector ( ) , x , y , z , 5 , 1 ) ;
2020-12-05 20:23:53 +00:00
spritetype * pMissile = & spawned - > s ( ) ;
2021-09-05 10:25:52 +00:00
pMissile - > cstat2 | = CSTAT2_SPRITE_MAPPED ;
2020-12-05 20:23:53 +00:00
pMissile - > type = nType ;
pMissile - > shade = pMissileInfo - > shade ;
pMissile - > pal = 0 ;
pMissile - > clipdist = pMissileInfo - > clipDist ;
pMissile - > flags = 1 ;
pMissile - > xrepeat = pMissileInfo - > xrepeat ;
pMissile - > yrepeat = pMissileInfo - > yrepeat ;
pMissile - > picnum = pMissileInfo - > picnum ;
pMissile - > ang = ( pSprite - > ang + pMissileInfo - > angleOfs ) & 2047 ;
2021-09-04 10:52:02 +00:00
spawned - > xvel = MulScale ( pMissileInfo - > velocity , a4 , 14 ) ;
spawned - > yvel = MulScale ( pMissileInfo - > velocity , a5 , 14 ) ;
spawned - > zvel = MulScale ( pMissileInfo - > velocity , a6 , 14 ) ;
2021-08-29 21:10:19 +00:00
spawned - > SetOwner ( actor ) ;
2021-12-18 18:19:28 +00:00
pMissile - > cstat | = CSTAT_SPRITE_BLOCK ;
2020-12-05 20:23:53 +00:00
spawned - > SetTarget ( nullptr ) ;
2021-08-27 07:44:47 +00:00
evPostActor ( spawned , 600 , kCallbackRemove ) ;
2020-12-05 20:23:53 +00:00
actBuildMissile ( spawned , actor ) ;
2021-11-16 17:30:23 +00:00
if ( impact )
2020-12-05 20:23:53 +00:00
{
actImpactMissile ( spawned , hit ) ;
return nullptr ;
}
return spawned ;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-08-30 18:21:49 +00:00
int actGetRespawnTime ( DBloodActor * actor )
{
spritetype * pSprite = & actor - > s ( ) ;
if ( ! actor - > hasX ( ) ) return - 1 ;
XSPRITE * pXSprite = & actor - > x ( ) ;
if ( actor - > IsDudeActor ( ) & & ! actor - > IsPlayerActor ( ) )
{
if ( pXSprite - > respawn = = 2 | | ( pXSprite - > respawn ! = 1 & & gGameOptions . nMonsterSettings = = 2 ) )
2021-09-16 19:59:39 +00:00
return gGameOptions . nMonsterRespawnTime ;
return - 1 ;
}
2019-10-13 22:29:19 +00:00
2021-08-30 18:21:49 +00:00
if ( actor - > IsWeaponActor ( ) )
{
2021-09-16 19:59:39 +00:00
if ( pXSprite - > respawn = = 3 | | gGameOptions . nWeaponSettings = = 1 ) return 0 ;
2021-08-30 18:21:49 +00:00
else if ( pXSprite - > respawn ! = 1 & & gGameOptions . nWeaponSettings ! = 0 )
2021-09-16 19:59:39 +00:00
return gGameOptions . nWeaponRespawnTime ;
return - 1 ;
}
2019-10-13 22:29:19 +00:00
2021-08-30 18:21:49 +00:00
if ( actor - > IsAmmoActor ( ) )
{
if ( pXSprite - > respawn = = 2 | | ( pXSprite - > respawn ! = 1 & & gGameOptions . nWeaponSettings ! = 0 ) )
2021-09-16 19:59:39 +00:00
return gGameOptions . nWeaponRespawnTime ;
return - 1 ;
}
2019-10-13 22:29:19 +00:00
2021-08-30 18:21:49 +00:00
if ( actor - > IsItemActor ( ) )
{
2021-09-16 19:59:39 +00:00
if ( pXSprite - > respawn = = 3 & & gGameOptions . nGameType = = 1 ) return 0 ;
2021-08-30 18:21:49 +00:00
else if ( pXSprite - > respawn = = 2 | | ( pXSprite - > respawn ! = 1 & & gGameOptions . nItemSettings ! = 0 ) )
{
switch ( pSprite - > type )
{
2021-09-16 19:59:39 +00:00
case kItemShadowCloak :
case kItemTwoGuns :
case kItemReflectShots :
return gGameOptions . nSpecialRespawnTime ;
case kItemDeathMask :
2021-08-30 18:21:49 +00:00
return gGameOptions . nSpecialRespawnTime < < 1 ;
2021-09-16 19:59:39 +00:00
default :
return gGameOptions . nItemRespawnTime ;
}
}
return - 1 ;
}
return - 1 ;
2019-09-19 22:42:45 +00:00
}
2021-08-30 18:21:49 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
bool actCheckRespawn ( DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2021-08-30 18:21:49 +00:00
spritetype * pSprite = & actor - > s ( ) ;
if ( actor - > hasX ( ) )
2021-09-16 19:59:39 +00:00
{
2021-08-30 18:21:49 +00:00
XSPRITE * pXSprite = & actor - > x ( ) ;
int nRespawnTime = actGetRespawnTime ( actor ) ;
if ( nRespawnTime < 0 ) return 0 ;
2021-09-16 19:59:39 +00:00
pXSprite - > respawnPending = 1 ;
if ( pSprite - > type > = kThingBase & & pSprite - > type < kThingMax )
{
pXSprite - > respawnPending = 3 ;
2021-12-18 15:02:15 +00:00
if ( pSprite - > type = = kThingTNTBarrel ) pSprite - > cstat | = CSTAT_SPRITE_INVISIBLE ;
2021-09-16 19:59:39 +00:00
}
if ( nRespawnTime > 0 )
{
2021-08-30 18:21:49 +00:00
if ( pXSprite - > respawnPending = = 1 ) nRespawnTime = MulScale ( nRespawnTime , 0xa000 , 16 ) ;
2021-09-16 19:59:39 +00:00
pSprite - > owner = pSprite - > statnum ;
2021-08-30 18:21:49 +00:00
actPostSprite ( actor , kStatRespawn ) ;
2021-09-16 19:59:39 +00:00
pSprite - > flags | = kHitagRespawn ;
2021-08-30 18:21:49 +00:00
2021-09-16 19:59:39 +00:00
if ( ! ( pSprite - > type > = kDudeBase & & pSprite - > type < kDudeMax ) )
{
2021-12-18 15:09:58 +00:00
pSprite - > cstat & = ~ CSTAT_SPRITE_BLOCK_ALL ;
2021-09-04 10:23:36 +00:00
pSprite - > pos = actor - > basePoint ;
2021-09-16 19:59:39 +00:00
}
2021-08-27 07:44:47 +00:00
evPostActor ( actor , nRespawnTime , kCallbackRespawn ) ;
2021-09-16 19:59:39 +00:00
}
return 1 ;
}
return 0 ;
2019-09-19 22:42:45 +00:00
}
2021-08-30 18:28:24 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-11-21 08:51:51 +00:00
bool actCanSplatWall ( walltype * pWall )
2019-09-19 22:42:45 +00:00
{
2021-12-18 14:36:50 +00:00
if ( pWall - > cstat & ( CSTAT_WALL_MOVE_MASK ) ) return 0 ;
2021-08-30 18:28:24 +00:00
2021-11-21 08:51:51 +00:00
int nType = pWall - > type ;
2021-08-30 18:28:24 +00:00
if ( nType > = kWallBase & & nType < kWallMax ) return 0 ;
2021-11-23 22:04:21 +00:00
if ( pWall - > twoSided ( ) )
2021-09-16 19:59:39 +00:00
{
2021-11-19 19:08:50 +00:00
sectortype * pSector = pWall - > nextSector ( ) ;
2021-08-30 18:28:24 +00:00
if ( pSector - > type > = kSectorBase & & pSector - > type < kSectorMax ) return 0 ;
2021-09-16 19:59:39 +00:00
}
return 1 ;
2019-09-19 22:42:45 +00:00
}
2021-08-30 18:28:24 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void actFireVector ( DBloodActor * shooter , int a2 , int a3 , int a4 , int a5 , int a6 , VECTOR_TYPE vectorType )
2019-09-19 22:42:45 +00:00
{
2021-08-30 18:28:24 +00:00
auto pShooter = & shooter - > s ( ) ;
2021-09-16 19:59:39 +00:00
assert ( vectorType > = 0 & & vectorType < kVectorMax ) ;
2021-08-30 18:28:24 +00:00
const VECTORDATA * pVectorData = & gVectorData [ vectorType ] ;
2021-09-16 19:59:39 +00:00
int nRange = pVectorData - > maxDist ;
2021-09-04 18:12:05 +00:00
int hit = VectorScan ( shooter , a2 , a3 , a4 , a5 , a6 , nRange , 1 ) ;
2021-09-16 19:59:39 +00:00
if ( hit = = 3 )
{
2021-11-25 22:28:28 +00:00
auto hitactor = gHitInfo . actor ( ) ;
2021-05-05 14:43:42 +00:00
assert ( hitactor ! = nullptr ) ;
spritetype * pSprite = & hitactor - > s ( ) ;
2021-09-16 19:59:39 +00:00
if ( ! gGameOptions . bFriendlyFire & & IsTargetTeammate ( pShooter , pSprite ) ) return ;
2021-08-30 18:28:24 +00:00
if ( IsPlayerSprite ( pSprite ) )
{
PLAYER * pPlayer = & gPlayer [ pSprite - > type - kDudePlayer1 ] ;
2021-09-16 19:59:39 +00:00
if ( powerupCheck ( pPlayer , kPwUpReflectShots ) )
{
2021-11-25 22:28:28 +00:00
gHitInfo . hitActor = shooter ;
2021-12-22 09:36:09 +00:00
gHitInfo . hitpos . X = pShooter - > x ;
2021-12-22 09:40:26 +00:00
gHitInfo . hitpos . Y = pShooter - > y ;
2021-12-22 09:41:47 +00:00
gHitInfo . hitpos . Z = pShooter - > z ;
2021-09-16 19:59:39 +00:00
}
}
}
2021-12-22 09:36:09 +00:00
int x = gHitInfo . hitpos . X - MulScale ( a4 , 16 , 14 ) ;
2021-12-22 09:40:26 +00:00
int y = gHitInfo . hitpos . Y - MulScale ( a5 , 16 , 14 ) ;
2021-12-22 09:41:47 +00:00
int z = gHitInfo . hitpos . Z - MulScale ( a6 , 256 , 14 ) ;
2021-11-25 22:28:28 +00:00
auto pSector = gHitInfo . hitSector ;
2021-09-16 19:59:39 +00:00
uint8_t nSurf = kSurfNone ;
2021-12-22 09:40:26 +00:00
if ( nRange = = 0 | | approxDist ( gHitInfo . hitpos . X - pShooter - > x , gHitInfo . hitpos . Y - pShooter - > y ) < nRange )
2021-09-16 19:59:39 +00:00
{
switch ( hit )
{
case 1 :
{
2021-12-18 12:14:56 +00:00
if ( pSector - > ceilingstat & CSTAT_SECTOR_SKY )
2021-09-16 19:59:39 +00:00
nSurf = kSurfNone ;
else
2021-11-23 16:00:00 +00:00
nSurf = surfType [ pSector - > ceilingpicnum ] ;
2021-09-16 19:59:39 +00:00
break ;
}
case 2 :
{
2021-12-18 12:14:56 +00:00
if ( pSector - > floorstat & CSTAT_SECTOR_SKY )
2021-09-16 19:59:39 +00:00
nSurf = kSurfNone ;
else
2021-11-23 16:00:00 +00:00
nSurf = surfType [ pSector - > floorpicnum ] ;
2021-09-16 19:59:39 +00:00
break ;
}
case 0 :
{
2021-11-23 16:00:00 +00:00
auto pWall = gHitInfo . hitWall ;
2021-11-19 19:35:33 +00:00
nSurf = surfType [ pWall - > picnum ] ;
2021-11-21 08:51:51 +00:00
if ( actCanSplatWall ( pWall ) )
2021-09-16 19:59:39 +00:00
{
2021-12-22 09:36:09 +00:00
int x = gHitInfo . hitpos . X - MulScale ( a4 , 16 , 14 ) ;
2021-12-22 09:40:26 +00:00
int y = gHitInfo . hitpos . Y - MulScale ( a5 , 16 , 14 ) ;
2021-12-22 09:41:47 +00:00
int z = gHitInfo . hitpos . Z - MulScale ( a6 , 256 , 14 ) ;
2021-11-19 19:35:33 +00:00
int nSurf = surfType [ pWall - > picnum ] ;
2021-09-16 19:59:39 +00:00
assert ( nSurf < kSurfMax ) ;
if ( pVectorData - > surfHit [ nSurf ] . fx1 > = 0 )
{
2021-11-23 16:00:00 +00:00
auto pFX = gFX . fxSpawnActor ( pVectorData - > surfHit [ nSurf ] . fx1 , pSector , x , y , z , 0 ) ;
2021-09-16 19:59:39 +00:00
if ( pFX )
{
2021-12-21 22:18:23 +00:00
pFX - > spr . ang = ( GetWallAngle ( pWall ) + 512 ) & 2047 ;
pFX - > spr . cstat | = CSTAT_SPRITE_ALIGNMENT_WALL ;
2021-09-16 19:59:39 +00:00
}
}
}
break ;
}
case 4 :
{
2021-11-23 16:00:00 +00:00
auto pWall = gHitInfo . hitWall ;
2021-11-19 14:46:20 +00:00
nSurf = surfType [ pWall - > overpicnum ] ;
if ( pWall - > hasX ( ) )
2021-09-16 19:59:39 +00:00
{
2021-11-19 14:46:20 +00:00
if ( pWall - > xw ( ) . triggerVector )
trTriggerWall ( pWall , kCmdWallImpact ) ;
2021-09-16 19:59:39 +00:00
}
break ;
}
case 3 :
{
2021-11-25 22:28:28 +00:00
auto actor = gHitInfo . actor ( ) ;
2021-08-30 18:28:24 +00:00
spritetype * pSprite = & actor - > s ( ) ;
nSurf = surfType [ pSprite - > picnum ] ;
2021-09-16 19:59:39 +00:00
x - = MulScale ( a4 , 112 , 14 ) ;
y - = MulScale ( a5 , 112 , 14 ) ;
2021-08-30 18:28:24 +00:00
z - = MulScale ( a6 , 112 < < 4 , 14 ) ;
2021-09-16 19:59:39 +00:00
int shift = 4 ;
2021-08-30 18:28:24 +00:00
if ( vectorType = = kVectorTine & & ! actor - > IsPlayerActor ( ) ) shift = 3 ;
actDamageSprite ( shooter , actor , pVectorData - > dmgType , pVectorData - > dmg < < shift ) ;
if ( actor - > hasX ( ) & & actor - > x ( ) . Vector ) trTriggerSprite ( actor , kCmdSpriteImpact ) ;
2021-09-16 19:59:39 +00:00
if ( pSprite - > statnum = = kStatThing )
{
2021-08-30 18:28:24 +00:00
int t = thingInfo [ pSprite - > type - kThingBase ] . mass ;
2021-09-16 19:59:39 +00:00
if ( t > 0 & & pVectorData - > impulse )
{
int t2 = DivScale ( pVectorData - > impulse , t , 8 ) ;
2021-09-04 10:52:02 +00:00
actor - > xvel + = MulScale ( a4 , t2 , 16 ) ;
actor - > yvel + = MulScale ( a5 , t2 , 16 ) ;
actor - > zvel + = MulScale ( a6 , t2 , 16 ) ;
2021-09-16 19:59:39 +00:00
}
if ( pVectorData - > burnTime )
{
2021-08-27 07:44:47 +00:00
if ( ! actor - > x ( ) . burnTime ) evPostActor ( actor , 0 , kCallbackFXFlameLick ) ;
2021-08-30 18:28:24 +00:00
actBurnSprite ( shooter - > GetOwner ( ) , actor , pVectorData - > burnTime ) ;
2021-09-16 19:59:39 +00:00
}
}
if ( pSprite - > statnum = = kStatDude & & actor - > hasX ( ) )
{
int t = getDudeInfo ( pSprite - > type ) - > mass ;
2021-08-30 18:28:24 +00:00
# ifdef NOONE_EXTENSIONS
if ( actor - > IsDudeActor ( ) )
{
switch ( pSprite - > type )
{
2021-09-16 19:59:39 +00:00
case kDudeModernCustom :
case kDudeModernCustomBurning :
2021-08-27 17:12:22 +00:00
t = getSpriteMassBySize ( actor ) ;
2021-09-16 19:59:39 +00:00
break ;
}
}
2021-08-30 18:28:24 +00:00
# endif
2019-09-19 22:42:45 +00:00
2021-09-16 19:59:39 +00:00
if ( t > 0 & & pVectorData - > impulse )
{
int t2 = DivScale ( pVectorData - > impulse , t , 8 ) ;
2021-09-04 10:52:02 +00:00
actor - > xvel + = MulScale ( a4 , t2 , 16 ) ;
actor - > yvel + = MulScale ( a5 , t2 , 16 ) ;
actor - > zvel + = MulScale ( a6 , t2 , 16 ) ;
2021-09-16 19:59:39 +00:00
}
if ( pVectorData - > burnTime )
{
2021-08-27 07:44:47 +00:00
if ( ! actor - > x ( ) . burnTime ) evPostActor ( actor , 0 , kCallbackFXFlameLick ) ;
2021-08-30 18:28:24 +00:00
actBurnSprite ( shooter - > GetOwner ( ) , actor , pVectorData - > burnTime ) ;
2021-09-16 19:59:39 +00:00
}
if ( Chance ( pVectorData - > fxChance ) )
{
int t = gVectorData [ 19 ] . maxDist ;
a4 + = Random3 ( 4000 ) ;
a5 + = Random3 ( 4000 ) ;
a6 + = Random3 ( 4000 ) ;
2021-12-22 09:41:47 +00:00
if ( HitScan ( actor , gHitInfo . hitpos . Z , a4 , a5 , a6 , CLIPMASK1 , t ) = = 0 )
2021-09-16 19:59:39 +00:00
{
2021-12-22 09:40:26 +00:00
if ( approxDist ( gHitInfo . hitpos . X - pSprite - > x , gHitInfo . hitpos . Y - pSprite - > y ) < = t )
2021-09-16 19:59:39 +00:00
{
2021-11-23 16:00:00 +00:00
auto pWall = gHitInfo . hitWall ;
2021-11-25 22:28:28 +00:00
auto pSector = gHitInfo . hitSector ;
2021-11-23 16:00:00 +00:00
if ( actCanSplatWall ( pWall ) )
2021-09-16 19:59:39 +00:00
{
2021-12-22 09:36:09 +00:00
int x = gHitInfo . hitpos . X - MulScale ( a4 , 16 , 14 ) ;
2021-12-22 09:40:26 +00:00
int y = gHitInfo . hitpos . Y - MulScale ( a5 , 16 , 14 ) ;
2021-12-22 09:41:47 +00:00
int z = gHitInfo . hitpos . Z - MulScale ( a6 , 16 < < 4 , 14 ) ;
2021-11-23 16:00:00 +00:00
int nSurf = surfType [ pWall - > picnum ] ;
2021-08-30 18:28:24 +00:00
const VECTORDATA * pVectorData = & gVectorData [ 19 ] ;
2021-09-16 19:59:39 +00:00
FX_ID t2 = pVectorData - > surfHit [ nSurf ] . fx2 ;
FX_ID t3 = pVectorData - > surfHit [ nSurf ] . fx3 ;
2021-08-30 18:28:24 +00:00
DBloodActor * pFX = nullptr ;
2021-11-23 16:00:00 +00:00
if ( t2 > FX_NONE & & ( t3 = = FX_NONE | | Chance ( 0x4000 ) ) ) pFX = gFX . fxSpawnActor ( t2 , pSector , x , y , z , 0 ) ;
else if ( t3 > FX_NONE ) pFX = gFX . fxSpawnActor ( t3 , pSector , x , y , z , 0 ) ;
2021-09-16 19:59:39 +00:00
if ( pFX )
{
2021-09-04 10:52:02 +00:00
pFX - > zvel = 0x2222 ;
2021-12-21 22:18:23 +00:00
pFX - > spr . ang = ( GetWallAngle ( pWall ) + 512 ) & 2047 ;
pFX - > spr . cstat | = CSTAT_SPRITE_ALIGNMENT_WALL ;
2021-09-16 19:59:39 +00:00
}
}
}
}
}
for ( int i = 0 ; i < pVectorData - > bloodSplats ; i + + )
if ( Chance ( pVectorData - > splatChance ) )
2021-08-26 22:07:33 +00:00
fxSpawnBlood ( actor , pVectorData - > dmg < < 4 ) ;
2021-09-16 19:59:39 +00:00
}
2021-08-30 18:28:24 +00:00
# ifdef NOONE_EXTENSIONS
2021-09-16 19:59:39 +00:00
// add impulse for sprites from physics list
2021-08-30 18:28:24 +00:00
if ( gPhysSpritesCount > 0 & & pVectorData - > impulse )
{
2021-09-16 19:59:39 +00:00
if ( actor - > hasX ( ) )
2021-08-30 18:28:24 +00:00
{
2021-09-16 19:59:39 +00:00
XSPRITE * pXSprite = & actor - > x ( ) ;
if ( pXSprite - > physAttr & kPhysDebrisVector ) {
2021-09-01 19:53:33 +00:00
int impulse = DivScale ( pVectorData - > impulse , ClipLow ( actor - > spriteMass . mass , 10 ) , 6 ) ;
2021-09-04 10:52:02 +00:00
actor - > xvel + = MulScale ( a4 , impulse , 16 ) ;
actor - > yvel + = MulScale ( a5 , impulse , 16 ) ;
actor - > zvel + = MulScale ( a6 , impulse , 16 ) ;
2021-07-19 21:15:26 +00:00
2021-09-16 19:59:39 +00:00
if ( pVectorData - > burnTime ! = 0 ) {
2021-08-27 07:44:47 +00:00
if ( ! pXSprite - > burnTime ) evPostActor ( actor , 0 , kCallbackFXFlameLick ) ;
2021-09-16 19:59:39 +00:00
actBurnSprite ( shooter - > GetOwner ( ) , actor , pVectorData - > burnTime ) ;
}
2021-07-19 21:15:26 +00:00
2021-09-16 19:59:39 +00:00
if ( pSprite - > type > = kThingBase & & pSprite - > type < kThingMax ) {
pSprite - > statnum = kStatThing ; // temporary change statnum property
actDamageSprite ( shooter , actor , pVectorData - > dmgType , pVectorData - > dmg < < 4 ) ;
pSprite - > statnum = kStatDecoration ; // return statnum property back
}
2021-07-19 21:15:26 +00:00
2021-09-16 19:59:39 +00:00
}
2019-09-21 11:02:17 +00:00
2021-07-19 21:15:26 +00:00
2021-09-16 19:59:39 +00:00
}
2021-07-19 21:15:26 +00:00
2021-09-16 19:59:39 +00:00
}
# endif
break ;
}
}
}
assert ( nSurf < kSurfMax ) ;
2021-07-19 21:15:26 +00:00
# ifdef NOONE_EXTENSIONS
2021-09-16 19:59:39 +00:00
// let the patrol enemies hear surface hit sounds!
if ( pVectorData - > surfHit [ nSurf ] . fx2 > = 0 ) {
2021-11-23 16:00:00 +00:00
auto pFX2 = gFX . fxSpawnActor ( pVectorData - > surfHit [ nSurf ] . fx2 , pSector , x , y , z , 0 ) ;
2021-09-16 19:59:39 +00:00
if ( pFX2 & & gModernMap )
2021-08-29 21:10:19 +00:00
pFX2 - > SetOwner ( shooter ) ;
2021-09-16 19:59:39 +00:00
}
if ( pVectorData - > surfHit [ nSurf ] . fx3 > = 0 ) {
2021-11-23 16:00:00 +00:00
auto pFX3 = gFX . fxSpawnActor ( pVectorData - > surfHit [ nSurf ] . fx3 , pSector , x , y , z , 0 ) ;
2021-09-16 19:59:39 +00:00
if ( pFX3 & & gModernMap )
2021-08-29 21:10:19 +00:00
pFX3 - > SetOwner ( shooter ) ;
2021-07-19 21:15:26 +00:00
2021-09-16 19:59:39 +00:00
}
2021-07-19 21:15:26 +00:00
# else
2021-09-16 19:59:39 +00:00
if ( pVectorData - > surfHit [ nSurf ] . fx2 > = 0 )
2021-11-23 16:00:00 +00:00
gFX . fxSpawnActor ( pVectorData - > surfHit [ nSurf ] . fx2 , pSector , x , y , z , 0 ) ;
2021-09-16 19:59:39 +00:00
if ( pVectorData - > surfHit [ nSurf ] . fx3 > = 0 )
2021-11-23 16:00:00 +00:00
gFX . fxSpawnActor ( pVectorData - > surfHit [ nSurf ] . fx3 , pSector , x , y , z , 0 ) ;
2021-07-19 21:15:26 +00:00
# endif
2021-09-16 19:59:39 +00:00
if ( pVectorData - > surfHit [ nSurf ] . fxSnd > = 0 )
2021-11-23 16:00:00 +00:00
sfxPlay3DSound ( x , y , z , pVectorData - > surfHit [ nSurf ] . fxSnd , pSector ) ;
2019-09-19 22:42:45 +00:00
}
2021-08-30 18:28:24 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-08-30 18:32:14 +00:00
2020-11-07 14:16:12 +00:00
void FireballSeqCallback ( int , DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2021-08-30 18:32:14 +00:00
auto pSprite = & actor - > s ( ) ;
2021-11-23 23:41:19 +00:00
auto pFX = gFX . fxSpawnActor ( FX_11 , pSprite - > sector ( ) , pSprite - > x , pSprite - > y , pSprite - > z , 0 ) ;
2021-09-16 19:59:39 +00:00
if ( pFX )
{
2021-09-04 10:52:02 +00:00
pFX - > xvel = actor - > xvel ;
pFX - > yvel = actor - > yvel ;
pFX - > zvel = actor - > zvel ;
2021-09-16 19:59:39 +00:00
}
2019-09-19 22:42:45 +00:00
}
2020-11-07 14:16:12 +00:00
void NapalmSeqCallback ( int , DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2021-08-30 18:32:14 +00:00
auto pSprite = & actor - > s ( ) ;
2021-11-23 23:41:19 +00:00
auto pFX = gFX . fxSpawnActor ( FX_12 , pSprite - > sector ( ) , pSprite - > x , pSprite - > y , pSprite - > z , 0 ) ;
2021-09-16 19:59:39 +00:00
if ( pFX )
{
2021-09-04 10:52:02 +00:00
pFX - > xvel = actor - > xvel ;
pFX - > yvel = actor - > yvel ;
pFX - > zvel = actor - > zvel ;
2021-09-16 19:59:39 +00:00
}
2019-09-19 22:42:45 +00:00
}
2021-08-30 18:32:14 +00:00
void Fx32Callback ( int , DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2021-08-30 18:32:14 +00:00
auto pSprite = & actor - > s ( ) ;
2021-11-23 23:41:19 +00:00
auto pFX = gFX . fxSpawnActor ( FX_32 , pSprite - > sector ( ) , pSprite - > x , pSprite - > y , pSprite - > z , 0 ) ;
2021-09-16 19:59:39 +00:00
if ( pFX )
{
2021-09-04 10:52:02 +00:00
pFX - > xvel = actor - > xvel ;
pFX - > yvel = actor - > yvel ;
pFX - > zvel = actor - > zvel ;
2021-09-16 19:59:39 +00:00
}
2019-09-19 22:42:45 +00:00
}
2021-08-30 18:32:14 +00:00
void Fx33Callback ( int , DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2021-08-30 18:32:14 +00:00
auto pSprite = & actor - > s ( ) ;
2021-11-23 23:41:19 +00:00
auto pFX = gFX . fxSpawnActor ( FX_33 , pSprite - > sector ( ) , pSprite - > x , pSprite - > y , pSprite - > z , 0 ) ;
2021-09-16 19:59:39 +00:00
if ( pFX )
{
2021-09-04 10:52:02 +00:00
pFX - > xvel = actor - > xvel ;
pFX - > yvel = actor - > yvel ;
pFX - > zvel = actor - > zvel ;
2021-09-16 19:59:39 +00:00
}
2019-09-19 22:42:45 +00:00
}
2021-08-30 18:32:14 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-11-07 14:16:12 +00:00
void TreeToGibCallback ( int , DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2021-09-16 19:59:39 +00:00
XSPRITE * pXSprite = & actor - > x ( ) ;
2021-08-30 18:32:14 +00:00
spritetype * pSprite = & actor - > s ( ) ;
2021-09-16 19:59:39 +00:00
pSprite - > type = kThingObjectExplode ;
pXSprite - > state = 1 ;
pXSprite - > data1 = 15 ;
pXSprite - > data2 = 0 ;
pXSprite - > data3 = 0 ;
pXSprite - > health = thingInfo [ 17 ] . startHealth ;
pXSprite - > data4 = 312 ;
2021-12-18 15:09:58 +00:00
pSprite - > cstat | = CSTAT_SPRITE_BLOCK_ALL ;
2019-09-19 22:42:45 +00:00
}
2020-11-07 14:16:12 +00:00
void DudeToGibCallback1 ( int , DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2021-09-16 19:59:39 +00:00
XSPRITE * pXSprite = & actor - > x ( ) ;
spritetype * pSprite = & actor - > s ( ) ;
pSprite - > type = kThingBloodChunks ;
pXSprite - > data1 = 8 ;
pXSprite - > data2 = 0 ;
pXSprite - > data3 = 0 ;
pXSprite - > health = thingInfo [ 26 ] . startHealth ;
pXSprite - > data4 = 319 ;
pXSprite - > triggerOnce = 0 ;
pXSprite - > isTriggered = 0 ;
pXSprite - > locked = 0 ;
pXSprite - > targetX = PlayClock ;
pXSprite - > state = 1 ;
2019-09-19 22:42:45 +00:00
}
2020-11-07 14:16:12 +00:00
void DudeToGibCallback2 ( int , DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2021-09-16 19:59:39 +00:00
XSPRITE * pXSprite = & actor - > x ( ) ;
spritetype * pSprite = & actor - > s ( ) ;
pSprite - > type = kThingBloodChunks ;
pXSprite - > data1 = 3 ;
pXSprite - > data2 = 0 ;
pXSprite - > data3 = 0 ;
pXSprite - > health = thingInfo [ 26 ] . startHealth ;
pXSprite - > data4 = 319 ;
pXSprite - > triggerOnce = 0 ;
pXSprite - > isTriggered = 0 ;
pXSprite - > locked = 0 ;
pXSprite - > targetX = PlayClock ;
pXSprite - > state = 1 ;
2019-09-19 22:42:45 +00:00
}
2021-08-30 18:12:19 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void actPostSprite ( DBloodActor * actor , int nStatus )
2019-09-19 22:42:45 +00:00
{
2021-09-16 19:59:39 +00:00
assert ( nStatus > = 0 & & nStatus < = kStatFree ) ;
2021-08-30 18:12:19 +00:00
auto sp = & actor - > s ( ) ;
if ( sp - > flags & 32 )
2021-09-16 19:59:39 +00:00
{
2021-08-30 18:12:19 +00:00
for ( auto & post : gPost )
if ( post . sprite = = actor )
{
post . status = nStatus ;
return ;
2021-09-16 19:59:39 +00:00
}
2021-08-30 18:12:19 +00:00
}
2021-09-16 19:59:39 +00:00
else
{
2021-08-30 18:12:19 +00:00
sp - > flags | = 32 ;
gPost . Push ( { actor , nStatus } ) ;
2021-09-16 19:59:39 +00:00
}
2020-12-02 21:33:14 +00:00
}
2019-09-19 22:42:45 +00:00
void actPostProcess ( void )
{
2021-08-30 18:12:19 +00:00
for ( auto & p : gPost )
2021-09-16 19:59:39 +00:00
{
2021-12-21 22:18:23 +00:00
p . sprite - > spr . flags & = ~ 32 ;
2021-08-30 18:12:19 +00:00
int nStatus = p . status ;
2021-09-16 19:59:39 +00:00
if ( nStatus = = kStatFree )
{
2021-12-21 22:18:23 +00:00
if ( p . sprite - > spr . statnum ! = kStatFree )
2021-08-26 06:10:18 +00:00
{
2021-08-27 07:44:47 +00:00
evKillActor ( p . sprite ) ;
2021-08-30 18:12:19 +00:00
if ( p . sprite - > hasX ( ) ) seqKill ( p . sprite ) ;
2021-08-29 20:04:35 +00:00
DeleteSprite ( p . sprite ) ;
2021-08-26 06:10:18 +00:00
}
2021-09-16 19:59:39 +00:00
}
else
2021-09-04 07:37:17 +00:00
ChangeActorStat ( p . sprite , nStatus ) ;
2021-09-16 19:59:39 +00:00
}
2021-08-30 18:12:19 +00:00
gPost . Clear ( ) ;
2019-09-19 22:42:45 +00:00
}
2021-08-30 18:12:19 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2020-11-06 21:48:22 +00:00
void MakeSplash ( DBloodActor * actor )
2019-09-19 22:42:45 +00:00
{
2021-09-16 19:59:39 +00:00
auto pSprite = & actor - > s ( ) ;
pSprite - > flags & = ~ 2 ;
pSprite - > z - = 4 < < 8 ;
2021-08-29 17:09:29 +00:00
int nSurface = tileGetSurfType ( actor - > hit . florhit ) ;
2021-08-30 18:32:14 +00:00
switch ( pSprite - > type )
{
2021-09-16 19:59:39 +00:00
case kThingDripWater :
2021-08-30 18:32:14 +00:00
switch ( nSurface )
{
2021-09-16 19:59:39 +00:00
case kSurfWater :
2021-08-30 18:32:14 +00:00
seqSpawn ( 6 , actor , - 1 ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 356 , - 1 , 0 ) ;
2021-09-16 19:59:39 +00:00
break ;
default :
2021-08-30 18:32:14 +00:00
seqSpawn ( 7 , actor , - 1 ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 354 , - 1 , 0 ) ;
2021-09-16 19:59:39 +00:00
break ;
}
break ;
case kThingDripBlood :
2021-08-30 18:32:14 +00:00
seqSpawn ( 8 , actor , - 1 ) ;
2021-09-16 19:34:16 +00:00
sfxPlay3DSound ( actor , 354 , - 1 , 0 ) ;
2021-09-16 19:59:39 +00:00
break ;
}
2019-09-19 22:42:45 +00:00
}
2021-08-29 17:22:51 +00:00
void actBurnSprite ( DBloodActor * pSource , DBloodActor * pTarget , int nTime )
{
auto pXSprite = & pTarget - > x ( ) ;
2021-12-21 22:18:23 +00:00
pXSprite - > burnTime = ClipHigh ( pXSprite - > burnTime + nTime , pTarget - > spr . statnum = = kStatDude ? 2400 : 1200 ) ;
2021-08-29 17:22:51 +00:00
pTarget - > SetBurnSource ( pSource ) ;
}
2020-11-21 20:31:50 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-09-19 22:42:45 +00:00
2020-11-21 22:40:33 +00:00
FSerializer & Serialize ( FSerializer & arc , const char * keyname , SPRITEHIT & w , SPRITEHIT * def )
{
2021-09-02 18:23:51 +00:00
if ( arc . BeginObject ( keyname ) )
{
arc ( " hit " , w . hit )
( " ceilhit " , w . ceilhit )
( " florhit " , w . florhit )
2021-09-16 19:59:39 +00:00
. EndObject ( ) ;
}
return arc ;
2020-11-21 22:40:33 +00:00
}
2020-11-21 20:31:50 +00:00
void SerializeActor ( FSerializer & arc )
2019-09-19 22:42:45 +00:00
{
2020-11-21 20:31:50 +00:00
if ( arc . BeginObject ( " actor " ) )
{
2021-06-16 19:13:04 +00:00
arc ( " maxdist20 " , gVectorData [ kVectorTchernobogBurn ] . maxDist ) // The code messes around with this field so better save it.
2020-11-21 20:31:50 +00:00
. EndObject ( ) ;
2021-08-30 18:12:19 +00:00
if ( arc . isReading ( ) & & gGameOptions . nMonsterSettings ! = 0 )
2020-11-21 20:31:50 +00:00
{
for ( int i = 0 ; i < kDudeMax - kDudeBase ; i + + )
for ( int j = 0 ; j < 7 ; j + + )
2020-12-02 23:30:19 +00:00
dudeInfo [ i ] . damageVal [ j ] = MulScale ( DudeDifficulty [ gGameOptions . nDifficulty ] , dudeInfo [ i ] . startDamage [ j ] , 8 ) ;
2020-11-21 20:31:50 +00:00
}
}
2019-09-19 22:42:45 +00:00
}
2019-09-22 06:39:22 +00:00
END_BLD_NS