2019-11-20 16:21:32 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
|
|
|
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
|
|
|
This file is part of PCExhumed.
|
|
|
|
PCExhumed 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-11-22 23:11:37 +00:00
|
|
|
#include "ns.h"
|
2019-08-26 03:59:14 +00:00
|
|
|
#include "engine.h"
|
2020-08-18 07:52:08 +00:00
|
|
|
#include "aistuff.h"
|
2019-08-26 03:59:14 +00:00
|
|
|
#include "sequence.h"
|
|
|
|
#include "exhumed.h"
|
|
|
|
#include "sound.h"
|
|
|
|
#include "player.h"
|
|
|
|
#include "names.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
2019-11-22 23:11:37 +00:00
|
|
|
BEGIN_PS_NS
|
|
|
|
|
2020-10-11 11:14:32 +00:00
|
|
|
enum { kMaxBullets = 500 };
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
// 32 bytes
|
|
|
|
struct Bullet
|
|
|
|
{
|
2021-12-07 17:53:02 +00:00
|
|
|
TObjPtr<DExhumedActor*> pActor;
|
|
|
|
TObjPtr<DExhumedActor*> pEnemy;
|
2021-10-16 19:21:04 +00:00
|
|
|
|
2021-11-21 18:33:51 +00:00
|
|
|
int16_t nSeq;
|
|
|
|
int16_t nFrame;
|
|
|
|
int16_t nRunRec;
|
|
|
|
int16_t nRunRec2;
|
|
|
|
int16_t nType;
|
|
|
|
int16_t nPitch;
|
2021-11-21 19:13:19 +00:00
|
|
|
int16_t field_E;
|
2019-10-01 17:59:20 +00:00
|
|
|
uint16_t field_10;
|
2019-09-25 21:16:12 +00:00
|
|
|
uint8_t field_12;
|
2021-10-16 20:14:30 +00:00
|
|
|
uint8_t nDoubleDamage;
|
2019-09-25 21:16:12 +00:00
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int z;
|
2019-08-26 03:59:14 +00:00
|
|
|
};
|
|
|
|
|
2020-11-30 00:10:52 +00:00
|
|
|
FreeListArray<Bullet, kMaxBullets> BulletList;
|
2019-08-26 03:59:14 +00:00
|
|
|
int lasthitz, lasthitx, lasthity;
|
2021-11-22 22:40:53 +00:00
|
|
|
sectortype* lasthitsect;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-12-07 17:53:02 +00:00
|
|
|
size_t MarkBullets()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < kMaxBullets; i++)
|
|
|
|
{
|
|
|
|
GC::Mark(BulletList[i].pActor);
|
|
|
|
GC::Mark(BulletList[i].pEnemy);
|
|
|
|
}
|
|
|
|
return 2 * kMaxBullets;
|
|
|
|
}
|
|
|
|
|
2021-11-21 19:13:19 +00:00
|
|
|
int nRadialBullet = 0;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2020-11-30 00:10:52 +00:00
|
|
|
FSerializer& Serialize(FSerializer& arc, const char* keyname, Bullet& w, Bullet* def)
|
|
|
|
{
|
|
|
|
static Bullet nul;
|
|
|
|
if (!def)
|
|
|
|
{
|
|
|
|
def = &nul;
|
|
|
|
if (arc.isReading()) w = {};
|
|
|
|
}
|
|
|
|
if (arc.BeginObject(keyname))
|
|
|
|
{
|
|
|
|
arc("seq", w.nSeq, def->nSeq)
|
|
|
|
("frame", w.nFrame, def->nFrame)
|
2021-10-16 19:21:04 +00:00
|
|
|
("sprite", w.pActor, def->pActor)
|
2020-11-30 00:10:52 +00:00
|
|
|
("type", w.nType, def->nType)
|
|
|
|
("x", w.x, def->x)
|
|
|
|
("y", w.y, def->y)
|
|
|
|
("z", w.z, def->z)
|
2021-11-21 18:33:51 +00:00
|
|
|
("at6", w.nRunRec, def->nRunRec)
|
|
|
|
("at8", w.nRunRec2, def->nRunRec2)
|
2021-10-19 22:26:26 +00:00
|
|
|
("atc", w.nPitch, def->nPitch)
|
2020-11-30 00:10:52 +00:00
|
|
|
("ate", w.field_E, def->field_E)
|
|
|
|
("at10", w.field_10, def->field_10)
|
|
|
|
("at12", w.field_12, def->field_12)
|
2021-10-16 20:14:30 +00:00
|
|
|
("at13", w.nDoubleDamage, def->nDoubleDamage)
|
2021-10-16 20:04:21 +00:00
|
|
|
("enemy", w.pEnemy, def->pEnemy)
|
2020-11-30 00:10:52 +00:00
|
|
|
.EndObject();
|
|
|
|
}
|
|
|
|
return arc;
|
|
|
|
}
|
2019-12-26 21:00:04 +00:00
|
|
|
|
2020-11-30 00:10:52 +00:00
|
|
|
void SerializeBullet(FSerializer& arc)
|
|
|
|
{
|
|
|
|
if (arc.BeginObject("bullets"))
|
|
|
|
{
|
|
|
|
arc ("list", BulletList)
|
|
|
|
("lasthitx", lasthitx)
|
|
|
|
("lasthity", lasthity)
|
|
|
|
("lasthitz", lasthitz)
|
|
|
|
("lasthitsect", lasthitsect)
|
|
|
|
("radialbullet", nRadialBullet)
|
|
|
|
.EndObject();
|
|
|
|
}
|
|
|
|
}
|
2019-12-26 21:00:04 +00:00
|
|
|
|
2019-08-26 03:59:14 +00:00
|
|
|
bulletInfo BulletInfo[] = {
|
2020-03-12 21:57:23 +00:00
|
|
|
{ 25, 1, 20, -1, -1, 13, 0, 0, -1 },
|
|
|
|
{ 25, -1, 65000, -1, 31, 73, 0, 0, -1 },
|
|
|
|
{ 15, -1, 60000, -1, 31, 73, 0, 0, -1 },
|
|
|
|
{ 5, 15, 2000, -1, 14, 38, 4, 5, 3 },
|
|
|
|
{ 250, 100, 2000, -1, 33, 34, 4, 20, -1 },
|
|
|
|
{ 200, -1, 2000, -1, 20, 23, 4, 10, -1 },
|
|
|
|
{ 200, -1, 60000, 68, 68, -1, -1, 0, -1 },
|
|
|
|
{ 300, 1, 0, -1, -1, -1, 0, 50, -1 },
|
|
|
|
{ 18, -1, 2000, -1, 18, 29, 4, 0, -1 },
|
|
|
|
{ 20, -1, 2000, 37, 11, 30, 4, 0, -1 },
|
|
|
|
{ 25, -1, 3000, -1, 44, 36, 4, 15, 90 },
|
|
|
|
{ 30, -1, 1000, -1, 52, 53, 4, 20, 48 },
|
|
|
|
{ 20, -1, 3500, -1, 54, 55, 4, 30, -1 },
|
|
|
|
{ 10, -1, 5000, -1, 57, 76, 4, 0, -1 },
|
|
|
|
{ 40, -1, 1500, -1, 63, 38, 4, 10, 40 },
|
|
|
|
{ 20, -1, 2000, -1, 60, 12, 0, 0, -1 },
|
|
|
|
{ 5, -1, 60000, -1, 31, 76, 0, 0, -1 }
|
2019-08-26 03:59:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void InitBullets()
|
|
|
|
{
|
2020-11-30 00:10:52 +00:00
|
|
|
BulletList.Clear();
|
2021-12-21 14:24:36 +00:00
|
|
|
lasthitsect = nullptr;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2020-11-30 00:10:52 +00:00
|
|
|
int GrabBullet()
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2020-11-30 00:10:52 +00:00
|
|
|
int grabbed = BulletList.Get();
|
|
|
|
if (grabbed < 0) return -1;
|
2021-10-16 20:04:21 +00:00
|
|
|
BulletList[grabbed].pEnemy = nullptr;
|
2020-11-30 00:10:52 +00:00
|
|
|
return grabbed;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
void DestroyBullet(int nBullet)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = BulletList[nBullet].pActor;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-11-21 18:33:51 +00:00
|
|
|
runlist_DoSubRunRec(BulletList[nBullet].nRunRec);
|
2021-12-23 16:02:35 +00:00
|
|
|
runlist_DoSubRunRec(pActor->spr.lotag - 1);
|
2021-11-21 18:33:51 +00:00
|
|
|
runlist_SubRunRec(BulletList[nBullet].nRunRec2);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-10-16 19:21:04 +00:00
|
|
|
StopActorSound(pActor);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-10-16 19:21:04 +00:00
|
|
|
DeleteActor(pActor);
|
2020-11-30 00:10:52 +00:00
|
|
|
BulletList.Release(nBullet);
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-10-16 22:01:06 +00:00
|
|
|
void IgniteSprite(DExhumedActor* pActor)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2021-12-23 16:02:35 +00:00
|
|
|
pActor->spr.hitag += 2;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2022-08-20 13:42:53 +00:00
|
|
|
auto pAnimActor = BuildAnim(nullptr, 38, 0, pActor->spr.pos, pActor->sector(), 40, 20);
|
2021-12-30 09:30:21 +00:00
|
|
|
|
2021-10-24 18:21:27 +00:00
|
|
|
if (pAnimActor)
|
|
|
|
{
|
2021-10-16 22:01:06 +00:00
|
|
|
pAnimActor->pTarget = pActor;
|
2021-10-24 18:21:27 +00:00
|
|
|
ChangeActorStat(pAnimActor, kStatIgnited);
|
2022-02-20 12:14:39 +00:00
|
|
|
pAnimActor->spr.yrepeat = (uint8_t)max(1, (tileHeight(pAnimActor->spr.picnum) * 32) / nFlameHeight);
|
2021-10-24 18:21:27 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2022-08-20 13:42:53 +00:00
|
|
|
void BulletHitsSprite(Bullet *pBullet, DExhumedActor* pBulletActor, DExhumedActor* pHitActor, const DVector3& pos, sectortype* pSector)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2021-11-22 22:40:53 +00:00
|
|
|
assert(pSector != nullptr);
|
2019-09-25 21:16:12 +00:00
|
|
|
|
|
|
|
bulletInfo *pBulletInfo = &BulletInfo[pBullet->nType];
|
|
|
|
|
2021-12-23 17:11:53 +00:00
|
|
|
int nStat = pHitActor->spr.statnum;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
|
|
|
switch (pBullet->nType)
|
|
|
|
{
|
|
|
|
case 3:
|
|
|
|
{
|
2020-02-27 01:03:13 +00:00
|
|
|
if (nStat > 107 || nStat == kStatAnubisDrum) {
|
2019-09-25 21:16:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-12-23 17:11:53 +00:00
|
|
|
pHitActor->spr.hitag++;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-12-23 17:11:53 +00:00
|
|
|
if (pHitActor->spr.hitag == 15) {
|
2021-10-19 22:38:21 +00:00
|
|
|
IgniteSprite(pHitActor);
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!RandomSize(2)) {
|
2022-08-20 13:42:53 +00:00
|
|
|
BuildAnim(nullptr, pBulletInfo->field_C, 0, pos, pSector, 40, pBulletInfo->nFlags);
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
case 14:
|
|
|
|
{
|
2020-02-27 01:03:13 +00:00
|
|
|
if (nStat > 107 || nStat == kStatAnubisDrum) {
|
2019-09-25 21:16:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// else - fall through to below cases
|
2021-10-19 22:38:21 +00:00
|
|
|
[[fallthrough]];
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
case 8:
|
|
|
|
case 9:
|
|
|
|
case 12:
|
|
|
|
case 13:
|
|
|
|
case 15:
|
|
|
|
case 16:
|
|
|
|
{
|
|
|
|
// loc_29E59
|
|
|
|
if (!nStat || nStat > 98) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = pBullet->pActor;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2020-02-27 01:03:13 +00:00
|
|
|
if (nStat == kStatAnubisDrum)
|
|
|
|
{
|
2022-08-16 21:15:49 +00:00
|
|
|
int nAngle = (pActor->int_ang() + 256) - RandomSize(9);
|
2020-02-27 01:03:13 +00:00
|
|
|
|
2021-12-23 17:11:53 +00:00
|
|
|
pHitActor->spr.xvel = bcos(nAngle, 1);
|
|
|
|
pHitActor->spr.yvel = bsin(nAngle, 1);
|
|
|
|
pHitActor->spr.zvel = (-(RandomSize(3) + 1)) << 8;
|
2020-02-27 01:03:13 +00:00
|
|
|
}
|
|
|
|
else
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-12-23 17:11:53 +00:00
|
|
|
int xVel = pHitActor->spr.xvel;
|
|
|
|
int yVel = pHitActor->spr.yvel;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2022-08-16 21:17:01 +00:00
|
|
|
pHitActor->spr.xvel = bcos(pActor->int_ang(), -2);
|
|
|
|
pHitActor->spr.yvel = bsin(pActor->int_ang(), -2);
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-19 22:38:21 +00:00
|
|
|
MoveCreature(pHitActor);
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-12-23 17:11:53 +00:00
|
|
|
pHitActor->spr.xvel = xVel;
|
|
|
|
pHitActor->spr.yvel = yVel;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// BHS_switchBreak:
|
2021-11-21 19:13:19 +00:00
|
|
|
int nDamage = pBulletInfo->nDamage;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-16 20:14:30 +00:00
|
|
|
if (pBullet->nDoubleDamage > 1) {
|
2019-09-25 21:16:12 +00:00
|
|
|
nDamage *= 2;
|
|
|
|
}
|
|
|
|
|
2021-10-19 22:38:21 +00:00
|
|
|
runlist_DamageEnemy(pHitActor, pBulletActor, nDamage);
|
2019-09-25 21:16:12 +00:00
|
|
|
|
|
|
|
if (nStat <= 90 || nStat >= 199)
|
|
|
|
{
|
2022-08-20 13:42:53 +00:00
|
|
|
BuildAnim(nullptr, pBulletInfo->field_C, 0, pos, pSector, 40, pBulletInfo->nFlags);
|
2019-09-25 21:16:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (nStat)
|
|
|
|
{
|
2020-02-27 01:03:13 +00:00
|
|
|
case kStatDestructibleSprite:
|
|
|
|
break;
|
|
|
|
case kStatAnubisDrum:
|
|
|
|
case 102:
|
|
|
|
case kStatExplodeTrigger:
|
|
|
|
case kStatExplodeTarget:
|
2022-08-20 13:42:53 +00:00
|
|
|
BuildAnim(nullptr, 12, 0, pos, pSector, 40, 0);
|
2020-02-27 01:03:13 +00:00
|
|
|
break;
|
|
|
|
default:
|
2022-08-20 13:42:53 +00:00
|
|
|
BuildAnim(nullptr, 39, 0, pos, pSector, 40, 0);
|
2020-02-27 01:03:13 +00:00
|
|
|
if (pBullet->nType > 2)
|
|
|
|
{
|
2022-08-20 13:42:53 +00:00
|
|
|
BuildAnim(nullptr, pBulletInfo->field_C, 0, pos, pSector, 40, pBulletInfo->nFlags);
|
2020-02-27 01:03:13 +00:00
|
|
|
}
|
|
|
|
break;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-16 17:41:34 +00:00
|
|
|
void BackUpBullet(int *x, int *y, int nAngle)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2020-11-14 08:45:08 +00:00
|
|
|
*x -= bcos(nAngle, -11);
|
|
|
|
*y -= bsin(nAngle, -11);
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
int MoveBullet(int nBullet)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2022-08-20 13:42:53 +00:00
|
|
|
|
2021-10-16 19:21:04 +00:00
|
|
|
DExhumedActor* hitactor = nullptr;
|
2021-11-22 22:40:53 +00:00
|
|
|
sectortype* pHitSect = nullptr;
|
|
|
|
walltype* pHitWall = nullptr;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
|
|
|
Bullet *pBullet = &BulletList[nBullet];
|
2021-11-21 19:13:19 +00:00
|
|
|
int nType = pBullet->nType;
|
2019-09-25 21:16:12 +00:00
|
|
|
bulletInfo *pBulletInfo = &BulletInfo[nType];
|
|
|
|
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = BulletList[nBullet].pActor;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2022-01-31 22:33:44 +00:00
|
|
|
int x = pActor->int_pos().X;
|
|
|
|
int y = pActor->int_pos().Y;
|
|
|
|
int z = pActor->int_pos().Z; // ebx
|
2021-12-30 15:51:56 +00:00
|
|
|
int nSectFlag = pActor->sector()->Flag;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
|
|
|
int x2, y2, z2;
|
2022-08-20 13:42:53 +00:00
|
|
|
DVector3 pos;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-16 19:21:04 +00:00
|
|
|
int nVal = 0;
|
|
|
|
Collision coll;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2019-10-01 17:59:20 +00:00
|
|
|
if (pBullet->field_10 < 30000)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pEnemyActor = BulletList[nBullet].pEnemy;
|
2021-10-16 20:04:21 +00:00
|
|
|
if (pEnemyActor)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-12-21 22:18:23 +00:00
|
|
|
if (!(pEnemyActor->spr.cstat & CSTAT_SPRITE_BLOCK_ALL))
|
2021-10-16 20:04:21 +00:00
|
|
|
BulletList[nBullet].pEnemy = nullptr;
|
2019-09-25 21:16:12 +00:00
|
|
|
else
|
|
|
|
{
|
2021-10-16 20:04:21 +00:00
|
|
|
coll = AngleChase(pActor, pEnemyActor, pBullet->field_10, 0, 16);
|
2019-09-25 21:16:12 +00:00
|
|
|
goto MOVEEND;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nType == 3)
|
|
|
|
{
|
|
|
|
if (pBullet->field_E < 8)
|
|
|
|
{
|
2021-12-23 16:02:35 +00:00
|
|
|
pActor->spr.xrepeat -= 1;
|
|
|
|
pActor->spr.yrepeat += 8;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
|
|
|
pBullet->z -= 200;
|
|
|
|
|
2021-12-23 16:02:35 +00:00
|
|
|
if (pActor->spr.shade < 90) {
|
|
|
|
pActor->spr.shade += 35;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pBullet->field_E == 3)
|
|
|
|
{
|
|
|
|
pBullet->nSeq = 45;
|
2020-03-02 21:08:31 +00:00
|
|
|
pBullet->nFrame = 0;
|
2021-12-23 16:02:35 +00:00
|
|
|
pActor->spr.xrepeat = 40;
|
|
|
|
pActor->spr.yrepeat = 40;
|
|
|
|
pActor->spr.shade = 0;
|
2022-01-31 18:57:12 +00:00
|
|
|
pActor->add_int_z(512);
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-23 16:02:35 +00:00
|
|
|
pActor->spr.xrepeat += 4;
|
|
|
|
pActor->spr.yrepeat += 4;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-23 16:02:35 +00:00
|
|
|
coll = movesprite(pActor, pBullet->x, pBullet->y, pBullet->z, pActor->spr.clipdist >> 1, pActor->spr.clipdist >> 1, CLIPMASK1);
|
2019-09-25 21:16:12 +00:00
|
|
|
|
|
|
|
MOVEEND:
|
2021-10-16 19:21:04 +00:00
|
|
|
if (coll.type || coll.exbits)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-10-16 19:21:04 +00:00
|
|
|
nVal = 1;
|
2022-01-31 22:33:44 +00:00
|
|
|
x2 = pActor->int_pos().X;
|
|
|
|
y2 = pActor->int_pos().Y;
|
|
|
|
z2 = pActor->int_pos().Z;
|
2022-08-20 13:42:53 +00:00
|
|
|
pos = pActor->spr.pos;
|
2021-12-30 15:51:56 +00:00
|
|
|
pHitSect = pActor->sector();
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-16 19:21:04 +00:00
|
|
|
switch (coll.type)
|
|
|
|
{
|
|
|
|
case kHitWall:
|
2021-11-26 13:26:03 +00:00
|
|
|
pHitWall = coll.hitWall;
|
2021-10-16 19:21:04 +00:00
|
|
|
goto HITWALL;
|
2022-01-24 23:57:59 +00:00
|
|
|
case kHitSprite:
|
2021-10-16 19:21:04 +00:00
|
|
|
if (!coll.exbits)
|
|
|
|
{
|
2021-11-26 13:26:03 +00:00
|
|
|
hitactor = coll.actor();
|
2021-10-16 19:21:04 +00:00
|
|
|
goto HITSPRITE;
|
|
|
|
}
|
2022-01-24 23:57:59 +00:00
|
|
|
default:
|
|
|
|
if (coll.exbits)
|
|
|
|
goto HITSECT;
|
|
|
|
break;
|
|
|
|
|
2021-10-16 19:21:04 +00:00
|
|
|
}
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
|
2021-10-16 19:21:04 +00:00
|
|
|
nVal = coll.type || coll.exbits? 1:0;
|
|
|
|
|
2021-12-01 23:13:07 +00:00
|
|
|
// pSprite's sector may have changed since we set nSectFlag ?
|
2021-12-30 15:51:56 +00:00
|
|
|
int nFlagVal = nSectFlag ^ pActor->sector()->Flag;
|
2019-09-25 21:16:12 +00:00
|
|
|
if (nFlagVal & kSectUnderwater)
|
|
|
|
{
|
|
|
|
DestroyBullet(nBullet);
|
|
|
|
nVal = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nVal == 0 && nType != 15 && nType != 3)
|
|
|
|
{
|
2022-08-20 14:19:07 +00:00
|
|
|
AddFlash(pActor->sector(), pActor->spr.pos, 0);
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-12-23 16:02:35 +00:00
|
|
|
if (pActor->spr.pal != 5) {
|
|
|
|
pActor->spr.pal = 1;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nVal = 1;
|
|
|
|
|
2021-10-16 20:04:21 +00:00
|
|
|
if (BulletList[nBullet].pEnemy)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-10-16 20:04:21 +00:00
|
|
|
hitactor = BulletList[nBullet].pEnemy;
|
2022-01-31 22:33:44 +00:00
|
|
|
x2 = hitactor->int_pos().X;
|
|
|
|
y2 = hitactor->int_pos().Y;
|
|
|
|
z2 = hitactor->int_pos().Z - (GetActorHeight(hitactor) >> 1);
|
2021-12-30 15:51:56 +00:00
|
|
|
pHitSect = hitactor->sector();
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-08-26 03:59:14 +00:00
|
|
|
vec3_t startPos = { x, y, z };
|
2021-12-06 11:24:22 +00:00
|
|
|
HitInfo hit{};
|
2019-10-27 16:36:25 +00:00
|
|
|
int dz;
|
|
|
|
if (bVanilla)
|
2021-10-19 22:26:26 +00:00
|
|
|
dz = -bsin(pBullet->nPitch, 3);
|
2019-10-27 16:36:25 +00:00
|
|
|
else
|
2021-10-19 22:26:26 +00:00
|
|
|
dz = -pBullet->nPitch * 512;
|
2022-08-16 21:17:01 +00:00
|
|
|
hitscan(startPos, pActor->sector(), { bcos(pActor->int_ang()), bsin(pActor->int_ang()), dz }, hit, CLIPMASK1);
|
2022-08-16 22:59:32 +00:00
|
|
|
x2 = hit.int_hitpos().X;
|
|
|
|
y2 = hit.int_hitpos().Y;
|
|
|
|
z2 = hit.int_hitpos().Z;
|
2021-11-25 23:25:28 +00:00
|
|
|
hitactor = hit.actor();
|
|
|
|
pHitSect = hit.hitSector;
|
|
|
|
pHitWall = hit.hitWall;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
2022-08-20 13:42:53 +00:00
|
|
|
pos = {x2 * inttoworld, y2 * inttoworld, z2 * zinttoworld};
|
2019-09-25 21:16:12 +00:00
|
|
|
|
|
|
|
lasthitx = x2;
|
|
|
|
lasthity = y2;
|
|
|
|
lasthitz = z2;
|
2021-11-22 22:40:53 +00:00
|
|
|
lasthitsect = pHitSect;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-16 19:21:04 +00:00
|
|
|
if (hitactor)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
|
|
|
HITSPRITE:
|
2021-12-23 17:11:53 +00:00
|
|
|
if (pActor->spr.pal == 5 && hitactor->spr.statnum == 100)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-11-16 17:50:02 +00:00
|
|
|
int nPlayer = GetPlayerFromActor(hitactor);
|
2019-09-25 21:16:12 +00:00
|
|
|
if (!PlayerList[nPlayer].bIsMummified)
|
|
|
|
{
|
2020-08-18 08:28:19 +00:00
|
|
|
PlayerList[nPlayer].bIsMummified = true;
|
2019-09-25 21:16:12 +00:00
|
|
|
SetNewWeapon(nPlayer, kWeaponMummified);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-20 13:42:53 +00:00
|
|
|
BulletHitsSprite(pBullet, pActor->pTarget, hitactor, pos, pHitSect);
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
}
|
2021-11-22 22:40:53 +00:00
|
|
|
else if (pHitWall != nullptr)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-11-22 21:20:53 +00:00
|
|
|
HITWALL:
|
2021-11-22 22:40:53 +00:00
|
|
|
if (pHitWall->picnum == kEnergy1)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-11-22 22:40:53 +00:00
|
|
|
if (pHitWall->twoSided())
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-11-21 19:13:19 +00:00
|
|
|
int nDamage = BulletInfo[pBullet->nType].nDamage;
|
2021-10-16 20:14:30 +00:00
|
|
|
if (pBullet->nDoubleDamage > 1) {
|
2019-09-25 21:16:12 +00:00
|
|
|
nDamage *= 2;
|
|
|
|
}
|
|
|
|
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* eb = EnergyBlocks[pHitWall->nextSector()->extra];
|
|
|
|
if (eb) runlist_DamageEnemy(eb, pActor, nDamage);
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-24 23:57:59 +00:00
|
|
|
HITSECT:
|
2021-11-22 22:40:53 +00:00
|
|
|
if (pHitSect != nullptr) // NOTE: hitsect can be -1. this check wasn't in original code. TODO: demo compatiblity?
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-11-22 22:40:53 +00:00
|
|
|
if (hitactor == nullptr && pHitWall == nullptr)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-11-22 22:05:48 +00:00
|
|
|
if ((pHitSect->pBelow != nullptr && (pHitSect->pBelow->Flag & kSectUnderwater)) || pHitSect->Depth)
|
2020-03-12 21:57:23 +00:00
|
|
|
{
|
2022-08-20 14:29:57 +00:00
|
|
|
pActor->spr.pos = pos;
|
2021-11-22 21:38:27 +00:00
|
|
|
BuildSplash(pActor, pHitSect);
|
2020-03-12 21:57:23 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-20 13:42:53 +00:00
|
|
|
BuildAnim(nullptr, pBulletInfo->field_C, 0, pos, pHitSect, 40, pBulletInfo->nFlags);
|
2020-03-12 21:57:23 +00:00
|
|
|
}
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-22 22:40:53 +00:00
|
|
|
if (pHitWall != nullptr)
|
2020-03-12 21:57:23 +00:00
|
|
|
{
|
2022-08-16 21:15:49 +00:00
|
|
|
BackUpBullet(&x2, &y2, pActor->int_ang());
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2020-03-12 21:57:23 +00:00
|
|
|
if (nType != 3 || RandomSize(2) == 0)
|
|
|
|
{
|
2022-08-20 13:42:53 +00:00
|
|
|
double zOffset = RandomSize(8) / 32.;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2020-03-12 21:57:23 +00:00
|
|
|
if (!RandomBit()) {
|
|
|
|
zOffset = -zOffset;
|
|
|
|
}
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2020-03-12 21:57:23 +00:00
|
|
|
// draws bullet puff on walls when they're shot
|
2022-08-20 13:42:53 +00:00
|
|
|
BuildAnim(nullptr, pBulletInfo->field_C, 0, pos.plusZ(zOffset - 16), pHitSect, 40, pBulletInfo->nFlags);
|
2020-03-12 21:57:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-20 14:29:57 +00:00
|
|
|
pActor->spr.pos = pos;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-11-22 22:40:53 +00:00
|
|
|
ChangeActorSect(pActor, pHitSect);
|
2020-03-12 21:57:23 +00:00
|
|
|
}
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2020-03-12 21:57:23 +00:00
|
|
|
if (BulletInfo[nType].nRadius)
|
|
|
|
{
|
|
|
|
nRadialBullet = nType;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-16 19:21:04 +00:00
|
|
|
runlist_RadialDamageEnemy(pActor, pBulletInfo->nDamage, pBulletInfo->nRadius);
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2020-03-12 21:57:23 +00:00
|
|
|
nRadialBullet = -1;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2022-08-20 14:19:07 +00:00
|
|
|
AddFlash(pActor->sector(), pActor->spr.pos, 128);
|
2020-03-12 21:57:23 +00:00
|
|
|
}
|
|
|
|
}
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DestroyBullet(nBullet);
|
|
|
|
}
|
|
|
|
|
|
|
|
return nVal;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
void SetBulletEnemy(int nBullet, DExhumedActor* pEnemy)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2019-09-25 21:16:12 +00:00
|
|
|
if (nBullet >= 0) {
|
2021-10-16 20:04:21 +00:00
|
|
|
BulletList[nBullet].pEnemy = pEnemy;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2022-08-20 15:44:55 +00:00
|
|
|
DExhumedActor* BuildBullet(DExhumedActor* pActor, int nType, int nZOffset, int nAngle, DExhumedActor* pTarget, int nDoubleDamage, int nPitch)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2019-09-25 21:16:12 +00:00
|
|
|
Bullet sBullet;
|
|
|
|
bulletInfo *pBulletInfo = &BulletInfo[nType];
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-09-25 21:16:12 +00:00
|
|
|
if (pBulletInfo->field_4 > 30000)
|
|
|
|
{
|
2021-10-19 22:26:26 +00:00
|
|
|
if (pTarget)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-12-23 17:11:53 +00:00
|
|
|
if (pTarget->spr.cstat & CSTAT_SPRITE_BLOCK_ALL)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
|
|
|
sBullet.nType = nType;
|
2021-10-16 20:14:30 +00:00
|
|
|
sBullet.nDoubleDamage = nDoubleDamage;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-12-30 15:51:56 +00:00
|
|
|
sBullet.pActor = insertActor(pActor->sector(), 200);
|
2022-08-16 21:21:10 +00:00
|
|
|
sBullet.pActor->set_int_ang(nAngle);
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2022-08-20 14:38:47 +00:00
|
|
|
double nHeight = GetActorHeightF(pTarget);
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-12-30 15:51:56 +00:00
|
|
|
assert(pTarget->sector());
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2022-08-20 14:38:47 +00:00
|
|
|
BulletHitsSprite(&sBullet, pActor, pTarget, pTarget->spr.pos.plusZ(-(nHeight * 0.5)), pTarget->sector());
|
2021-10-16 19:21:04 +00:00
|
|
|
DeleteActor(sBullet.pActor);
|
2021-10-19 22:26:26 +00:00
|
|
|
return nullptr;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-19 22:26:26 +00:00
|
|
|
nPitch = 0;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-30 00:10:52 +00:00
|
|
|
int nBullet = GrabBullet();
|
|
|
|
if (nBullet < 0) {
|
2021-10-19 22:26:26 +00:00
|
|
|
return nullptr;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
|
2021-11-22 23:20:15 +00:00
|
|
|
sectortype* pSector;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-12-23 16:02:35 +00:00
|
|
|
if (pActor->spr.statnum == 100)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-11-22 23:20:15 +00:00
|
|
|
pSector = PlayerList[GetPlayerFromActor(pActor)].pPlayerViewSect;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
pSector = pActor->sector();
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
|
2021-11-22 23:20:15 +00:00
|
|
|
auto pBulletActor = insertActor(pSector, 200);
|
2021-12-23 17:11:53 +00:00
|
|
|
int nHeight = GetActorHeight(pActor);
|
2019-09-25 21:16:12 +00:00
|
|
|
nHeight = nHeight - (nHeight >> 2);
|
|
|
|
|
2021-10-16 20:14:30 +00:00
|
|
|
if (nZOffset == -1) {
|
|
|
|
nZOffset = -nHeight;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
|
2022-08-16 21:46:18 +00:00
|
|
|
pBulletActor->spr.pos = pActor->spr.pos;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
|
|
|
Bullet *pBullet = &BulletList[nBullet];
|
|
|
|
|
2021-10-16 20:04:21 +00:00
|
|
|
pBullet->pEnemy = nullptr;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-12-23 17:11:53 +00:00
|
|
|
pBulletActor->spr.cstat = 0;
|
|
|
|
pBulletActor->spr.shade = -64;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
|
|
|
if (pBulletInfo->nFlags & 4) {
|
2021-12-23 17:11:53 +00:00
|
|
|
pBulletActor->spr.pal = 4;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
else {
|
2021-12-23 17:11:53 +00:00
|
|
|
pBulletActor->spr.pal = 0;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
|
2021-12-23 17:11:53 +00:00
|
|
|
pBulletActor->spr.clipdist = 25;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
int nRepeat = pBulletInfo->xyRepeat;
|
2019-09-25 21:16:12 +00:00
|
|
|
if (nRepeat < 0) {
|
|
|
|
nRepeat = 30;
|
|
|
|
}
|
|
|
|
|
2021-12-23 17:11:53 +00:00
|
|
|
pBulletActor->spr.xrepeat = (uint8_t)nRepeat;
|
|
|
|
pBulletActor->spr.yrepeat = (uint8_t)nRepeat;
|
|
|
|
pBulletActor->spr.xoffset = 0;
|
|
|
|
pBulletActor->spr.yoffset = 0;
|
2022-08-16 21:21:10 +00:00
|
|
|
pBulletActor->set_int_ang(nAngle);
|
2021-12-23 17:11:53 +00:00
|
|
|
pBulletActor->spr.xvel = 0;
|
|
|
|
pBulletActor->spr.yvel = 0;
|
|
|
|
pBulletActor->spr.zvel = 0;
|
|
|
|
pBulletActor->spr.lotag = runlist_HeadRun() + 1;
|
|
|
|
pBulletActor->spr.extra = -1;
|
|
|
|
pBulletActor->spr.hitag = 0;
|
2021-10-19 22:38:21 +00:00
|
|
|
pBulletActor->pTarget = pActor;
|
2021-10-19 22:26:26 +00:00
|
|
|
pBulletActor->nPhase = nBullet;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
|
|
|
// GrabTimeSlot(3);
|
|
|
|
|
2019-09-25 21:16:12 +00:00
|
|
|
pBullet->field_10 = 0;
|
|
|
|
pBullet->field_E = pBulletInfo->field_2;
|
2020-03-02 21:08:31 +00:00
|
|
|
pBullet->nFrame = 0;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
int nSeq;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
|
|
|
if (pBulletInfo->field_8 != -1)
|
|
|
|
{
|
|
|
|
pBullet->field_12 = 0;
|
|
|
|
nSeq = pBulletInfo->field_8;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pBullet->field_12 = 1;
|
|
|
|
nSeq = pBulletInfo->nSeq;
|
|
|
|
}
|
|
|
|
|
|
|
|
pBullet->nSeq = nSeq;
|
|
|
|
|
2021-12-23 17:11:53 +00:00
|
|
|
pBulletActor->spr.picnum = seq_GetSeqPicnum(nSeq, 0, 0);
|
2019-09-25 21:16:12 +00:00
|
|
|
|
|
|
|
if (nSeq == kSeqBullet) {
|
2021-12-23 17:11:53 +00:00
|
|
|
pBulletActor->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
|
2021-10-19 22:26:26 +00:00
|
|
|
pBullet->nPitch = nPitch;
|
2019-09-25 21:16:12 +00:00
|
|
|
pBullet->nType = nType;
|
2021-10-16 19:21:04 +00:00
|
|
|
pBullet->pActor = pBulletActor;
|
2021-12-23 17:11:53 +00:00
|
|
|
pBullet->nRunRec = runlist_AddRunRec(pBulletActor->spr.lotag - 1, nBullet, 0xB0000);
|
2021-11-21 18:33:51 +00:00
|
|
|
pBullet->nRunRec2 = runlist_AddRunRec(NewRun, nBullet, 0xB0000);
|
2021-10-16 20:14:30 +00:00
|
|
|
pBullet->nDoubleDamage = nDoubleDamage;
|
2022-01-31 18:57:12 +00:00
|
|
|
pBulletActor->add_int_z(nZOffset);
|
2021-12-30 16:10:08 +00:00
|
|
|
pBulletActor->backuppos();
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-11-07 22:33:39 +00:00
|
|
|
int var_18 = 0;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-12-30 15:51:56 +00:00
|
|
|
pSector = pBulletActor->sector();
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2022-08-20 14:44:30 +00:00
|
|
|
while (pBulletActor->spr.pos.Z < pSector->ceilingz)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-11-22 22:05:48 +00:00
|
|
|
if (pSector->pAbove == nullptr)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2022-08-20 14:44:30 +00:00
|
|
|
pBulletActor->spr.pos.Z = pSector->ceilingz;
|
2019-09-25 21:16:12 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-22 22:05:48 +00:00
|
|
|
pSector = pSector->pAbove;
|
|
|
|
ChangeActorSect(pBulletActor, pSector);
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
|
2021-10-19 22:26:26 +00:00
|
|
|
if (pTarget == nullptr)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-10-19 22:26:26 +00:00
|
|
|
var_18 = (-bsin(nPitch) * pBulletInfo->field_4) >> 11;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((unsigned int)pBulletInfo->field_4 > 30000)
|
|
|
|
{
|
2021-10-19 22:26:26 +00:00
|
|
|
BulletList[nBullet].pEnemy = pTarget;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-19 22:26:26 +00:00
|
|
|
nHeight = GetActorHeight(pTarget);
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-12-23 17:11:53 +00:00
|
|
|
if (pTarget->spr.statnum == 100)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
|
|
|
nHeight -= nHeight >> 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nHeight -= nHeight >> 1;
|
|
|
|
}
|
|
|
|
|
2022-01-31 22:33:44 +00:00
|
|
|
int var_20 = pTarget->int_pos().Z - nHeight;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
|
|
|
int x, y;
|
|
|
|
|
2021-12-23 16:02:35 +00:00
|
|
|
if (pActor != nullptr && pActor->spr.statnum != 100)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2022-01-31 22:33:44 +00:00
|
|
|
x = pTarget->int_pos().X;
|
|
|
|
y = pTarget->int_pos().Y;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-12-23 17:11:53 +00:00
|
|
|
if (pTarget->spr.statnum != 100)
|
2019-09-25 21:16:12 +00:00
|
|
|
{
|
2021-12-23 17:11:53 +00:00
|
|
|
x += (pTarget->spr.xvel * 20) >> 6;
|
|
|
|
y += (pTarget->spr.yvel * 20) >> 6;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-19 22:26:26 +00:00
|
|
|
int nPlayer = GetPlayerFromActor(pTarget);
|
2019-09-25 21:16:12 +00:00
|
|
|
if (nPlayer > -1)
|
|
|
|
{
|
2021-12-30 12:10:12 +00:00
|
|
|
x += PlayerList[nPlayer].nPlayerD.X * 15;
|
|
|
|
y += PlayerList[nPlayer].nPlayerD.Y * 15;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-31 22:33:44 +00:00
|
|
|
x -= pBulletActor->int_pos().X;
|
|
|
|
y -= pBulletActor->int_pos().Y;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
|
|
|
nAngle = GetMyAngle(x, y);
|
2022-08-16 21:21:10 +00:00
|
|
|
pActor->set_int_ang(nAngle);
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// loc_2ABA3:
|
2022-01-31 22:33:44 +00:00
|
|
|
x = pTarget->int_pos().X - pBulletActor->int_pos().X;
|
|
|
|
y = pTarget->int_pos().Y - pBulletActor->int_pos().Y;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int nSqrt = lsqrt(y*y + x*x);
|
|
|
|
if ((unsigned int)nSqrt > 0)
|
|
|
|
{
|
2022-01-31 22:33:44 +00:00
|
|
|
var_18 = ((var_20 - pBulletActor->int_pos().Z) * pBulletInfo->field_4) / nSqrt;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var_18 = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pBullet->z = 0;
|
2021-12-23 16:02:35 +00:00
|
|
|
pBullet->x = (pActor->spr.clipdist << 2) * bcos(nAngle);
|
|
|
|
pBullet->y = (pActor->spr.clipdist << 2) * bsin(nAngle);
|
2021-10-16 20:04:21 +00:00
|
|
|
BulletList[nBullet].pEnemy = nullptr;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-19 22:26:26 +00:00
|
|
|
|
2019-09-25 21:16:12 +00:00
|
|
|
if (MoveBullet(nBullet))
|
|
|
|
{
|
2021-10-16 19:21:04 +00:00
|
|
|
pBulletActor = nullptr;
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pBullet->field_10 = pBulletInfo->field_4;
|
2020-11-14 08:45:08 +00:00
|
|
|
pBullet->x = bcos(nAngle, -3) * pBulletInfo->field_4;
|
|
|
|
pBullet->y = bsin(nAngle, -3) * pBulletInfo->field_4;
|
2019-09-25 21:16:12 +00:00
|
|
|
pBullet->z = var_18 >> 3;
|
|
|
|
}
|
|
|
|
|
2021-10-19 22:26:26 +00:00
|
|
|
return pBulletActor;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-10-15 19:10:16 +00:00
|
|
|
void AIBullet::Tick(RunListEvent* ev)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2021-11-21 18:24:46 +00:00
|
|
|
int nBullet = RunData[ev->nRun].nObjIndex;
|
2019-09-25 21:16:12 +00:00
|
|
|
assert(nBullet >= 0 && nBullet < kMaxBullets);
|
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
int nSeq = SeqOffsets[BulletList[nBullet].nSeq];
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = BulletList[nBullet].pActor;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
int nFlag = FrameFlag[SeqBase[nSeq] + BulletList[nBullet].nFrame];
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-16 19:21:04 +00:00
|
|
|
seq_MoveSequence(pActor, nSeq, BulletList[nBullet].nFrame);
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-15 19:10:16 +00:00
|
|
|
if (nFlag & 0x80)
|
|
|
|
{
|
2022-08-20 13:42:53 +00:00
|
|
|
BuildAnim(nullptr, 45, 0, pActor->spr.pos, pActor->sector(), pActor->spr.xrepeat, 0);
|
2021-10-15 19:10:16 +00:00
|
|
|
}
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-15 19:10:16 +00:00
|
|
|
BulletList[nBullet].nFrame++;
|
|
|
|
if (BulletList[nBullet].nFrame >= SeqSize[nSeq])
|
|
|
|
{
|
|
|
|
if (!BulletList[nBullet].field_12)
|
|
|
|
{
|
|
|
|
BulletList[nBullet].nSeq = BulletInfo[BulletList[nBullet].nType].nSeq;
|
|
|
|
BulletList[nBullet].field_12++;
|
|
|
|
}
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-15 19:10:16 +00:00
|
|
|
BulletList[nBullet].nFrame = 0;
|
|
|
|
}
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-15 19:10:16 +00:00
|
|
|
if (BulletList[nBullet].field_E != -1 && --BulletList[nBullet].field_E == 0)
|
|
|
|
{
|
|
|
|
DestroyBullet(nBullet);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MoveBullet(nBullet);
|
|
|
|
}
|
|
|
|
}
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-15 19:10:16 +00:00
|
|
|
void AIBullet::Draw(RunListEvent* ev)
|
|
|
|
{
|
2021-11-21 18:24:46 +00:00
|
|
|
int nBullet = RunData[ev->nRun].nObjIndex;
|
2021-10-15 19:10:16 +00:00
|
|
|
assert(nBullet >= 0 && nBullet < kMaxBullets);
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
int nSeq = SeqOffsets[BulletList[nBullet].nSeq];
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-19 22:38:21 +00:00
|
|
|
ev->pTSprite->statnum = 1000;
|
2019-09-25 21:16:12 +00:00
|
|
|
|
2021-10-15 19:10:16 +00:00
|
|
|
if (BulletList[nBullet].nType == 15)
|
|
|
|
{
|
2021-10-26 06:13:23 +00:00
|
|
|
seq_PlotArrowSequence(ev->nParam, nSeq, BulletList[nBullet].nFrame);
|
2019-09-25 21:16:12 +00:00
|
|
|
}
|
2021-10-15 19:10:16 +00:00
|
|
|
else
|
|
|
|
{
|
2021-10-26 06:13:23 +00:00
|
|
|
seq_PlotSequence(ev->nParam, nSeq, BulletList[nBullet].nFrame, 0);
|
2021-12-04 18:08:50 +00:00
|
|
|
ev->pTSprite->ownerActor = nullptr;
|
2021-10-15 19:10:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-22 23:11:37 +00:00
|
|
|
END_PS_NS
|