From 69283bfb0c638a2986b868a7756e2cd1a14f36ce Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 29 Dec 2021 20:03:42 +0100 Subject: [PATCH] - tabified several Blood source files. --- source/common/textures/animlib.cpp | 294 +- source/common/textures/animlib.h | 76 +- source/common/textures/animtexture.cpp | 148 +- source/core/maphack.cpp | 704 ++-- source/games/blood/src/aiunicult.cpp | 3794 +++++++++++----------- source/games/blood/src/animatesprite.cpp | 1744 +++++----- source/games/blood/src/asound.cpp | 18 + source/games/blood/src/barf.cpp | 60 + source/games/blood/src/blood.cpp | 78 + source/games/blood/src/blood.h | 22 +- source/games/blood/src/bloodactor.h | 4 +- source/games/blood/src/callback.cpp | 1342 ++++---- source/games/blood/src/callback.h | 60 +- source/games/blood/src/choke.cpp | 18 + source/games/blood/src/common_game.h | 1030 +++--- source/games/blood/src/controls.cpp | 62 +- source/games/blood/src/d_menu.cpp | 18 + 17 files changed, 4934 insertions(+), 4538 deletions(-) diff --git a/source/common/textures/animlib.cpp b/source/common/textures/animlib.cpp index c712ae2bf..e42386bd9 100644 --- a/source/common/textures/animlib.cpp +++ b/source/common/textures/animlib.cpp @@ -44,38 +44,38 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) static inline uint16_t findpage(anim_t *anim, uint16_t framenumber) { - // curlpnum is initialized to 0xffff, obviously - size_t i = anim->curlpnum & ~0xffff; - size_t const nLps = anim->lpheader->nLps; - bool j = true; + // curlpnum is initialized to 0xffff, obviously + size_t i = anim->curlpnum & ~0xffff; + size_t const nLps = anim->lpheader->nLps; + bool j = true; - if (framenumber < anim->currentframe) - i = 0, j = false; + if (framenumber < anim->currentframe) + i = 0, j = false; - // this scans the last used page and higher first and then scans the - // previously accessed pages afterwards if it doesn't find anything - do - { - for (; i < nLps; ++i) - { - lp_descriptor & lp = anim->LpArray[i]; - if (lp.baseRecord <= framenumber && framenumber < lp.baseRecord + lp.nRecords) - return (uint16_t)i; - } + // this scans the last used page and higher first and then scans the + // previously accessed pages afterwards if it doesn't find anything + do + { + for (; i < nLps; ++i) + { + lp_descriptor & lp = anim->LpArray[i]; + if (lp.baseRecord <= framenumber && framenumber < lp.baseRecord + lp.nRecords) + return (uint16_t)i; + } - if (j && i == nLps) - { - // handle out of order pages... I don't think any Duke .ANM files - // have them, but they're part of the file spec - i = 0, j = false; - continue; - } + if (j && i == nLps) + { + // handle out of order pages... I don't think any Duke .ANM files + // have them, but they're part of the file spec + i = 0, j = false; + continue; + } - break; - } - while (1); + break; + } + while (1); - return (uint16_t)i; + return (uint16_t)i; } @@ -88,13 +88,13 @@ static inline uint16_t findpage(anim_t *anim, uint16_t framenumber) static inline void loadpage(anim_t *anim, uint16_t pagenumber, uint16_t **pagepointer) { - if (anim->curlpnum == pagenumber) - return; + if (anim->curlpnum == pagenumber) + return; - anim->curlpnum = pagenumber; - anim->curlp = &anim->LpArray[pagenumber]; - *pagepointer = (uint16_t *)(anim->buffer + 0xb00 + (pagenumber*IMAGEBUFFERSIZE) + - sizeof(lp_descriptor) + sizeof(uint16_t)); + anim->curlpnum = pagenumber; + anim->curlp = &anim->LpArray[pagenumber]; + *pagepointer = (uint16_t *)(anim->buffer + 0xb00 + (pagenumber*IMAGEBUFFERSIZE) + + sizeof(lp_descriptor) + sizeof(uint16_t)); } @@ -114,63 +114,63 @@ static inline void loadpage(anim_t *anim, uint16_t pagenumber, uint16_t **pagepo static void decodeframe(uint8_t * srcP, uint8_t * dstP) { - do - { - { - /* short op */ - uint8_t count = *srcP++; + do + { + { + /* short op */ + uint8_t count = *srcP++; - if (!count) /* short RLE */ - { - uint8_t color = *(srcP+1); - count = *(uint8_t *)srcP; - srcP += sizeof(int16_t); - memset(dstP, color, count); - dstP += count; - continue; - } - else if ((count & 0x80) == 0) /* short copy */ - { - memcpy(dstP, srcP, count); - dstP += count; - srcP += count; - continue; - } - else if ((count &= ~0x80) > 0) /* short skip */ - { - dstP += count; - continue; - } - } + if (!count) /* short RLE */ + { + uint8_t color = *(srcP+1); + count = *(uint8_t *)srcP; + srcP += sizeof(int16_t); + memset(dstP, color, count); + dstP += count; + continue; + } + else if ((count & 0x80) == 0) /* short copy */ + { + memcpy(dstP, srcP, count); + dstP += count; + srcP += count; + continue; + } + else if ((count &= ~0x80) > 0) /* short skip */ + { + dstP += count; + continue; + } + } - { - /* long op */ - uint16_t count = LittleShort((uint16_t)GetShort(srcP)); - srcP += sizeof(int16_t); + { + /* long op */ + uint16_t count = LittleShort((uint16_t)GetShort(srcP)); + srcP += sizeof(int16_t); - if (!count) /* stop sign */ - return; - else if ((count & 0x8000) == 0) /* long skip */ - { - dstP += count; - continue; - } - else if ((count &= ~0x8000) & 0x4000) /* long RLE */ - { - uint8_t color = *srcP++; - count &= ~0x4000; - memset(dstP, color, count); - dstP += count; - continue; - } + if (!count) /* stop sign */ + return; + else if ((count & 0x8000) == 0) /* long skip */ + { + dstP += count; + continue; + } + else if ((count &= ~0x8000) & 0x4000) /* long RLE */ + { + uint8_t color = *srcP++; + count &= ~0x4000; + memset(dstP, color, count); + dstP += count; + continue; + } - /* long copy */ - memcpy(dstP, srcP, count); - dstP += count; - srcP += count; - } - } - while (1); + /* long copy */ + memcpy(dstP, srcP, count); + dstP += count; + srcP += count; + } + } + while (1); } @@ -183,23 +183,23 @@ static void decodeframe(uint8_t * srcP, uint8_t * dstP) static void renderframe(anim_t *anim, uint16_t framenumber, uint16_t *pagepointer) { - uint16_t offset = 0; - uint16_t frame = framenumber - anim->curlp->baseRecord; + uint16_t offset = 0; + uint16_t frame = framenumber - anim->curlp->baseRecord; - while (frame--) offset += LittleShort(pagepointer[frame]); + while (frame--) offset += LittleShort(pagepointer[frame]); if (offset >= anim->curlp->nBytes) return; - uint8_t *ppointer = (uint8_t *)(pagepointer) + anim->curlp->nRecords*2 + offset + 4; + uint8_t *ppointer = (uint8_t *)(pagepointer) + anim->curlp->nRecords*2 + offset + 4; - if ((ppointer-4)[1]) - { - uint16_t const temp = LittleShort(((uint16_t *)(ppointer-4))[1]); - ppointer += temp + (temp & 1); - } + if ((ppointer-4)[1]) + { + uint16_t const temp = LittleShort(((uint16_t *)(ppointer-4))[1]); + ppointer += temp + (temp & 1); + } - decodeframe((uint8_t *)ppointer, (uint8_t *)anim->imagebuffer); + decodeframe((uint8_t *)ppointer, (uint8_t *)anim->imagebuffer); } @@ -212,79 +212,79 @@ static void renderframe(anim_t *anim, uint16_t framenumber, uint16_t *pagepointe static inline void drawframe(anim_t *anim, uint16_t framenumber) { - loadpage(anim, findpage(anim, framenumber), &anim->thepage); - renderframe(anim, framenumber, anim->thepage); + loadpage(anim, findpage(anim, framenumber), &anim->thepage); + renderframe(anim, framenumber, anim->thepage); } // is the file size, for consistency checking. int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, int32_t length) { - if (memcmp(buffer, "LPF ", 4)) return -1; + if (memcmp(buffer, "LPF ", 4)) return -1; - length -= sizeof(lpfileheader)+128+768; - if (length < 0) - return -1; + length -= sizeof(lpfileheader)+128+768; + if (length < 0) + return -1; - anim->curlpnum = 0xffff; - anim->currentframe = -1; + anim->curlpnum = 0xffff; + anim->currentframe = -1; - // this just modifies the data in-place instead of copying it elsewhere now - lpfileheader & lpheader = *(anim->lpheader = (lpfileheader *)(anim->buffer = buffer)); + // this just modifies the data in-place instead of copying it elsewhere now + lpfileheader & lpheader = *(anim->lpheader = (lpfileheader *)(anim->buffer = buffer)); - lpheader.id = LittleLong(lpheader.id); - lpheader.maxLps = LittleShort(lpheader.maxLps); - lpheader.nLps = LittleShort(lpheader.nLps); - lpheader.nRecords = LittleLong(lpheader.nRecords); - lpheader.maxRecsPerLp = LittleShort(lpheader.maxRecsPerLp); - lpheader.lpfTableOffset = LittleShort(lpheader.lpfTableOffset); - lpheader.contentType = LittleLong(lpheader.contentType); - lpheader.width = LittleShort(lpheader.width); - lpheader.height = LittleShort(lpheader.height); - lpheader.nFrames = LittleLong(lpheader.nFrames); - lpheader.framesPerSecond = LittleShort(lpheader.framesPerSecond); + lpheader.id = LittleLong(lpheader.id); + lpheader.maxLps = LittleShort(lpheader.maxLps); + lpheader.nLps = LittleShort(lpheader.nLps); + lpheader.nRecords = LittleLong(lpheader.nRecords); + lpheader.maxRecsPerLp = LittleShort(lpheader.maxRecsPerLp); + lpheader.lpfTableOffset = LittleShort(lpheader.lpfTableOffset); + lpheader.contentType = LittleLong(lpheader.contentType); + lpheader.width = LittleShort(lpheader.width); + lpheader.height = LittleShort(lpheader.height); + lpheader.nFrames = LittleLong(lpheader.nFrames); + lpheader.framesPerSecond = LittleShort(lpheader.framesPerSecond); - length -= lpheader.nLps * sizeof(lp_descriptor); - if (length < 0) - return -2; + length -= lpheader.nLps * sizeof(lp_descriptor); + if (length < 0) + return -2; - buffer += sizeof(lpfileheader)+128; + buffer += sizeof(lpfileheader)+128; - // load the color palette - for (uint8_t * pal = anim->pal, * pal_end = pal+768; pal < pal_end; pal += 3, buffer += 4) - { - pal[2] = buffer[0]; - pal[1] = buffer[1]; - pal[0] = buffer[2]; - } + // load the color palette + for (uint8_t * pal = anim->pal, * pal_end = pal+768; pal < pal_end; pal += 3, buffer += 4) + { + pal[2] = buffer[0]; + pal[1] = buffer[1]; + pal[0] = buffer[2]; + } - // set up large page descriptors - anim->LpArray = (lp_descriptor *)buffer; + // set up large page descriptors + anim->LpArray = (lp_descriptor *)buffer; - // theoretically we should be able to play files with more than 256 frames now - // assuming the utilities to create them can make them that way - for (lp_descriptor * lp = anim->LpArray, * lp_end = lp+lpheader.nLps; lp < lp_end; ++lp) - { - lp->baseRecord = LittleShort(lp->baseRecord); - lp->nRecords = LittleShort(lp->nRecords); - lp->nBytes = LittleShort(lp->nBytes); - } - return ANIM_NumFrames(anim) <= 0 ? -1 : 0; + // theoretically we should be able to play files with more than 256 frames now + // assuming the utilities to create them can make them that way + for (lp_descriptor * lp = anim->LpArray, * lp_end = lp+lpheader.nLps; lp < lp_end; ++lp) + { + lp->baseRecord = LittleShort(lp->baseRecord); + lp->nRecords = LittleShort(lp->nRecords); + lp->nBytes = LittleShort(lp->nBytes); + } + return ANIM_NumFrames(anim) <= 0 ? -1 : 0; } uint8_t * ANIM_DrawFrame(anim_t *anim, int32_t framenumber) { - uint32_t cnt = anim->currentframe; + uint32_t cnt = anim->currentframe; - // handle first play and looping or rewinding - if (cnt > (uint32_t)framenumber) - cnt = 0; + // handle first play and looping or rewinding + if (cnt > (uint32_t)framenumber) + cnt = 0; - do drawframe(anim, cnt++); - while (cnt < (uint32_t)framenumber); + do drawframe(anim, cnt++); + while (cnt < (uint32_t)framenumber); - anim->currentframe = framenumber; - return anim->imagebuffer; + anim->currentframe = framenumber; + return anim->imagebuffer; } diff --git a/source/common/textures/animlib.h b/source/common/textures/animlib.h index dd9415aa4..23d0d89da 100644 --- a/source/common/textures/animlib.h +++ b/source/common/textures/animlib.h @@ -45,37 +45,37 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au) struct lpfileheader { - uint32_t id; /* 4 uint8_tacter ID == "LPF " */ - uint16_t maxLps; /* max # largePages allowed. 256 FOR NOW. */ - uint16_t nLps; /* # largePages in this file. */ - uint32_t nRecords; /* # records in this file. 65534 is current limit + ring */ - uint16_t maxRecsPerLp; /* # records permitted in an lp. 256 FOR NOW. */ - uint16_t lpfTableOffset; /* Absolute Seek position of lpfTable. 1280 FOR NOW. */ - uint32_t contentType; /* 4 character ID == "ANIM" */ - uint16_t width; /* Width of screen in pixels. */ - uint16_t height; /* Height of screen in pixels. */ - uint8_t variant; /* 0==ANIM. */ - uint8_t version; /* 0==frame rate in 18/sec, 1= 70/sec */ - uint8_t hasLastDelta; /* 1==Last record is a delta from last-to-first frame. */ - uint8_t lastDeltaValid; /* 0==Ignore ring frame. */ - uint8_t pixelType; /* 0==256 color. */ - uint8_t CompressionType; /* 1==(RunSkipDump) Only one used FOR NOW. */ - uint8_t otherRecsPerFrm; /* 0 FOR NOW. */ - uint8_t bitmaptype; /* 1==320x200, 256-color. Only one implemented so far. */ - uint8_t recordTypes[32]; /* Not yet implemented. */ - uint32_t nFrames; /* Number of actual frames in the file, includes ring frame. */ - uint16_t framesPerSecond; /* Number of frames to play per second. */ - uint16_t pad2[29]; /* 58 bytes of filler to round up to 128 bytes total. */ + uint32_t id; /* 4 uint8_tacter ID == "LPF " */ + uint16_t maxLps; /* max # largePages allowed. 256 FOR NOW. */ + uint16_t nLps; /* # largePages in this file. */ + uint32_t nRecords; /* # records in this file. 65534 is current limit + ring */ + uint16_t maxRecsPerLp; /* # records permitted in an lp. 256 FOR NOW. */ + uint16_t lpfTableOffset; /* Absolute Seek position of lpfTable. 1280 FOR NOW. */ + uint32_t contentType; /* 4 character ID == "ANIM" */ + uint16_t width; /* Width of screen in pixels. */ + uint16_t height; /* Height of screen in pixels. */ + uint8_t variant; /* 0==ANIM. */ + uint8_t version; /* 0==frame rate in 18/sec, 1= 70/sec */ + uint8_t hasLastDelta; /* 1==Last record is a delta from last-to-first frame. */ + uint8_t lastDeltaValid; /* 0==Ignore ring frame. */ + uint8_t pixelType; /* 0==256 color. */ + uint8_t CompressionType; /* 1==(RunSkipDump) Only one used FOR NOW. */ + uint8_t otherRecsPerFrm; /* 0 FOR NOW. */ + uint8_t bitmaptype; /* 1==320x200, 256-color. Only one implemented so far. */ + uint8_t recordTypes[32]; /* Not yet implemented. */ + uint32_t nFrames; /* Number of actual frames in the file, includes ring frame. */ + uint16_t framesPerSecond; /* Number of frames to play per second. */ + uint16_t pad2[29]; /* 58 bytes of filler to round up to 128 bytes total. */ }; // this is the format of a large page structure struct lp_descriptor { - uint16_t baseRecord; // Number of first record in this large page. - uint16_t nRecords; // Number of records in lp. - // bit 15 of "nRecords" == "has continuation from previous lp". - // bit 14 of "nRecords" == "final record continues on next lp". - uint16_t nBytes; // Total number of bytes of contents, excluding header. + uint16_t baseRecord; // Number of first record in this large page. + uint16_t nRecords; // Number of records in lp. + // bit 15 of "nRecords" == "has continuation from previous lp". + // bit 14 of "nRecords" == "final record continues on next lp". + uint16_t nBytes; // Total number of bytes of contents, excluding header. }; #pragma pack(pop) @@ -84,16 +84,16 @@ struct lp_descriptor struct anim_t { - uint16_t framecount; // current frame of anim - lpfileheader * lpheader; // file header will be loaded into this structure - lp_descriptor * LpArray; // arrays of large page structs used to find frames - uint16_t curlpnum; // initialize to an invalid Large page number - lp_descriptor * curlp; // header of large page currently in memory - uint16_t * thepage; // buffer where current large page is loaded - uint8_t imagebuffer[IMAGEBUFFERSIZE]; // buffer where anim frame is decoded - uint8_t * buffer; - uint8_t pal[768]; - int32_t currentframe; + uint16_t framecount; // current frame of anim + lpfileheader * lpheader; // file header will be loaded into this structure + lp_descriptor * LpArray; // arrays of large page structs used to find frames + uint16_t curlpnum; // initialize to an invalid Large page number + lp_descriptor * curlp; // header of large page currently in memory + uint16_t * thepage; // buffer where current large page is loaded + uint8_t imagebuffer[IMAGEBUFFERSIZE]; // buffer where anim frame is decoded + uint8_t * buffer; + uint8_t pal[768]; + int32_t currentframe; }; //**************************************************************************** @@ -116,7 +116,7 @@ int32_t ANIM_LoadAnim(anim_t *anim, uint8_t *buffer, int32_t length); inline int32_t ANIM_NumFrames(anim_t* anim) { - return anim->lpheader->nRecords; + return anim->lpheader->nRecords; } //**************************************************************************** @@ -138,7 +138,7 @@ uint8_t * ANIM_DrawFrame(anim_t* anim, int32_t framenumber); inline uint8_t* ANIM_GetPalette(anim_t* anim) { - return anim->pal; + return anim->pal; } #endif diff --git a/source/common/textures/animtexture.cpp b/source/common/textures/animtexture.cpp index 039021641..a3be03079 100644 --- a/source/common/textures/animtexture.cpp +++ b/source/common/textures/animtexture.cpp @@ -44,42 +44,42 @@ void AnimTexture::SetFrameSize(int format, int width, int height) { - pixelformat = format; - FTexture::SetSize(width, height); - Image.Resize(width * height * (format == Paletted ? 1 : 3)); - memset(Image.Data(), 0, Image.Size()); + pixelformat = format; + FTexture::SetSize(width, height); + Image.Resize(width * height * (format == Paletted ? 1 : 3)); + memset(Image.Data(), 0, Image.Size()); } void AnimTexture::SetFrame(const uint8_t* palette, const void* data_) { - if (palette) memcpy(Palette, palette, 768); - if (data_) - { - if (pixelformat == YUV) - { - auto spix = (const uint8_t*)data_; - auto dpix = Image.Data(); - for (int i = 0; i < Width * Height; i++) - { - int p = i * 4; - int q = i * 3; - float y = spix[p] * (1 / 255.f); - float u = spix[p + 1] * (1 / 255.f) - 0.5f; - float v = spix[p + 2] * (1 / 255.f) - 0.5f; + if (palette) memcpy(Palette, palette, 768); + if (data_) + { + if (pixelformat == YUV) + { + auto spix = (const uint8_t*)data_; + auto dpix = Image.Data(); + for (int i = 0; i < Width * Height; i++) + { + int p = i * 4; + int q = i * 3; + float y = spix[p] * (1 / 255.f); + float u = spix[p + 1] * (1 / 255.f) - 0.5f; + float v = spix[p + 2] * (1 / 255.f) - 0.5f; - y = 1.1643f * (y - 0.0625f); + y = 1.1643f * (y - 0.0625f); - float r = y + 1.5958f * v; - float g = y - 0.39173f * u - 0.81290f * v; - float b = y + 2.017f * u; + float r = y + 1.5958f * v; + float g = y - 0.39173f * u - 0.81290f * v; + float b = y + 2.017f * u; - dpix[q + 0] = (uint8_t)(clamp(r, 0.f, 1.f) * 255); - dpix[q + 1] = (uint8_t)(clamp(g, 0.f, 1.f) * 255); - dpix[q + 2] = (uint8_t)(clamp(b, 0.f, 1.f) * 255); - } - } - else memcpy(Image.Data(), data_, Width * Height * (pixelformat == Paletted ? 1 : 3)); - } + dpix[q + 0] = (uint8_t)(clamp(r, 0.f, 1.f) * 255); + dpix[q + 1] = (uint8_t)(clamp(g, 0.f, 1.f) * 255); + dpix[q + 2] = (uint8_t)(clamp(b, 0.f, 1.f) * 255); + } + } + else memcpy(Image.Data(), data_, Width * Height * (pixelformat == Paletted ? 1 : 3)); + } } //=========================================================================== @@ -90,37 +90,37 @@ void AnimTexture::SetFrame(const uint8_t* palette, const void* data_) FBitmap AnimTexture::GetBgraBitmap(const PalEntry* remap, int* trans) { - FBitmap bmp; + FBitmap bmp; - bmp.Create(Width, Height); + bmp.Create(Width, Height); - auto spix = Image.Data(); - auto dpix = bmp.GetPixels(); - if (pixelformat == Paletted) - { - for (int i = 0; i < Width * Height; i++) - { - int p = i * 4; - int index = spix[i]; - dpix[p + 0] = Palette[index * 3 + 2]; - dpix[p + 1] = Palette[index * 3 + 1]; - dpix[p + 2] = Palette[index * 3]; - dpix[p + 3] = 255; - } - } - else if (pixelformat == RGB || pixelformat == YUV) - { - for (int i = 0; i < Width * Height; i++) - { - int p = i * 4; - int q = i * 3; - dpix[p + 0] = spix[q + 2]; - dpix[p + 1] = spix[q + 1]; - dpix[p + 2] = spix[q]; - dpix[p + 3] = 255; - } - } - return bmp; + auto spix = Image.Data(); + auto dpix = bmp.GetPixels(); + if (pixelformat == Paletted) + { + for (int i = 0; i < Width * Height; i++) + { + int p = i * 4; + int index = spix[i]; + dpix[p + 0] = Palette[index * 3 + 2]; + dpix[p + 1] = Palette[index * 3 + 1]; + dpix[p + 2] = Palette[index * 3]; + dpix[p + 3] = 255; + } + } + else if (pixelformat == RGB || pixelformat == YUV) + { + for (int i = 0; i < Width * Height; i++) + { + int p = i * 4; + int q = i * 3; + dpix[p + 0] = spix[q + 2]; + dpix[p + 1] = spix[q + 1]; + dpix[p + 2] = spix[q]; + dpix[p + 3] = 255; + } + } + return bmp; } //========================================================================== @@ -131,36 +131,36 @@ FBitmap AnimTexture::GetBgraBitmap(const PalEntry* remap, int* trans) AnimTextures::AnimTextures() { - active = 1; - tex[0] = TexMan.FindGameTexture("AnimTextureFrame1", ETextureType::Override); - tex[1] = TexMan.FindGameTexture("AnimTextureFrame2", ETextureType::Override); + active = 1; + tex[0] = TexMan.FindGameTexture("AnimTextureFrame1", ETextureType::Override); + tex[1] = TexMan.FindGameTexture("AnimTextureFrame2", ETextureType::Override); } AnimTextures::~AnimTextures() { - Clean(); + Clean(); } void AnimTextures::Clean() { - if (tex[0]) tex[0]->CleanHardwareData(true); - if (tex[1]) tex[1]->CleanHardwareData(true); - tex[0] = tex[1] = nullptr; + if (tex[0]) tex[0]->CleanHardwareData(true); + if (tex[1]) tex[1]->CleanHardwareData(true); + tex[0] = tex[1] = nullptr; } void AnimTextures::SetSize(int format, int width, int height) { - static_cast(tex[0]->GetTexture())->SetFrameSize(format, width, height); - static_cast(tex[1]->GetTexture())->SetFrameSize(format, width, height); - tex[0]->SetSize(width, height); - tex[1]->SetSize(width, height); - tex[0]->CleanHardwareData(); - tex[1]->CleanHardwareData(); + static_cast(tex[0]->GetTexture())->SetFrameSize(format, width, height); + static_cast(tex[1]->GetTexture())->SetFrameSize(format, width, height); + tex[0]->SetSize(width, height); + tex[1]->SetSize(width, height); + tex[0]->CleanHardwareData(); + tex[1]->CleanHardwareData(); } void AnimTextures::SetFrame(const uint8_t* palette, const void* data) { - active ^= 1; - static_cast(tex[active]->GetTexture())->SetFrame(palette, data); - tex[active]->CleanHardwareData(); + active ^= 1; + static_cast(tex[active]->GetTexture())->SetFrame(palette, data); + tex[active]->CleanHardwareData(); } diff --git a/source/core/maphack.cpp b/source/core/maphack.cpp index dee679645..b6e1b66fa 100644 --- a/source/core/maphack.cpp +++ b/source/core/maphack.cpp @@ -44,379 +44,379 @@ static TArray usermaphacks; void AddUserMapHack(usermaphack_t& mhk) { - usermaphacks.Push(mhk); + usermaphacks.Push(mhk); } static int32_t LoadMapHack(const char *filename, SpawnSpriteDef& sprites) { - int currentsprite = -1; - int currentwall = -1; - int currentsector = -1; - int numsprites = sprites.sprites.Size(); + int currentsprite = -1; + int currentwall = -1; + int currentsector = -1; + int numsprites = sprites.sprites.Size(); - FScanner sc; - int lump = fileSystem.FindFile(filename); - if (lump < 0) - { - return -1; - } - sc.OpenLumpNum(lump); - sprites.sprext.Resize(numsprites); - memset(sprites.sprext.Data(), 0, sizeof(spriteext_t) * sprites.sprext.Size()); + FScanner sc; + int lump = fileSystem.FindFile(filename); + if (lump < 0) + { + return -1; + } + sc.OpenLumpNum(lump); + sprites.sprext.Resize(numsprites); + memset(sprites.sprext.Data(), 0, sizeof(spriteext_t) * sprites.sprext.Size()); - while (sc.GetString()) - { - FString token = sc.String; - auto validateSprite = [&]() - { - if (currentsprite < 0 || currentsprite >= numsprites) - { - sc.ScriptMessage("Using %s without a valid sprite", token.GetChars()); - return false; - } - return true; - }; + while (sc.GetString()) + { + FString token = sc.String; + auto validateSprite = [&]() + { + if (currentsprite < 0 || currentsprite >= numsprites) + { + sc.ScriptMessage("Using %s without a valid sprite", token.GetChars()); + return false; + } + return true; + }; - auto validateWall = [&]() - { - if (currentwall < 0 || currentwall >= (int)wall.Size()) - { - sc.ScriptMessage("Using %s without a valid wall", token.GetChars()); - return false; - } - return true; - }; + auto validateWall = [&]() + { + if (currentwall < 0 || currentwall >= (int)wall.Size()) + { + sc.ScriptMessage("Using %s without a valid wall", token.GetChars()); + return false; + } + return true; + }; - auto validateSector = [&]() - { - if (currentsector < 0 || currentsector >= (int)sector.Size()) - { - sc.ScriptMessage("Using %s without a valid sector", token.GetChars()); - return false; - } - return true; - }; + auto validateSector = [&]() + { + if (currentsector < 0 || currentsector >= (int)sector.Size()) + { + sc.ScriptMessage("Using %s without a valid sector", token.GetChars()); + return false; + } + return true; + }; - if (sc.Compare("sprite")) - { - currentwall = -1; - currentsector = -1; - if (sc.CheckNumber()) - { - currentsprite = sc.Number; - if ((unsigned)currentsprite >= sprites.sprites.Size()) - { - sc.ScriptMessage("Invalid sprite number %d", currentsprite); - currentsprite = -1; - } - } - else currentsprite = -1; - } - if (sc.Compare("wall")) - { - currentsprite = -1; - currentsector = -1; - if (sc.CheckNumber()) - { - currentwall = sc.Number; - if (!validWallIndex(currentwall)) - { - sc.ScriptMessage("Invalid wall number %d", currentwall); - currentwall = -1; - } - } - else currentwall = -1; - } - if (sc.Compare("sector")) - { - currentsprite = -1; - currentwall = -1; - if (sc.CheckNumber()) - { - currentsector = sc.Number; - if (!validSectorIndex(currentsector)) - { - sc.ScriptMessage("Invalid sector number %d", currentsector); - currentsector = -1; - } - } - else currentsector = -1; - } - else if (sc.Compare("sector")) - { - if (sc.CheckNumber()) - { - if (currentsprite != -1 && validateSprite()) - { - sprites.sprites[currentsprite].setsector(sc.Number); - } - } - } - else if (sc.Compare("picnum")) - { - if (sc.CheckNumber()) - { - if (currentwall != -1 && validateWall()) - { - wall[currentwall].picnum = sc.Number; - } - else if (currentsprite != -1 && validateSprite()) - { - sprites.sprites[currentsprite].picnum = sc.Number; - } - } - } - else if (sc.Compare("overpicnum")) - { - if (sc.CheckNumber() && validateWall()) - { - wall[currentwall].overpicnum = sc.Number; - } - } - else if (sc.Compare("overpicnum")) - { - if (sc.CheckNumber() && validateWall()) - { - wall[currentwall].overpicnum = sc.Number; - } - } - else if (sc.Compare("split")) - { - int start = -1, end = -1; - if (sc.CheckNumber()) start = sc.Number; - if (sc.CheckNumber()) end = sc.Number; - if (end >= 0 && validateSector()) - { - hw_SetSplitSector(currentsector, start, end); - } - } - else if (sc.Compare("clearflags")) - { - if (currentsector != -1 && validateSector()) - { - sc.GetString(); - if (sc.Compare("floor") && sc.CheckNumber()) - { - sector[currentsector].floorstat &= ESectorFlags::FromInt(~sc.Number); - } - else if (sc.Compare("ceiling") && sc.CheckNumber()) - { - sector[currentsector].ceilingstat &= ESectorFlags::FromInt(~sc.Number); - } - else sc.ScriptError("Bad token %s", sc.String); - } - else if (sc.CheckNumber()) - { - if (currentwall != -1 && validateWall()) - { - wall[currentwall].cstat &= EWallFlags::FromInt(~sc.Number); - } - else if (currentsprite != -1 && validateSprite()) - { - sprites.sprites[currentsprite].cstat &= ESpriteFlags::FromInt(~sc.Number); - } - } - } - else if (sc.Compare("setflags")) - { - if (sc.CheckNumber()) - { - if (currentwall != -1 && validateWall()) - { - wall[currentwall].cstat |= EWallFlags::FromInt(sc.Number); - } - else if (currentsprite != -1 && validateSprite()) - { - sprites.sprites[currentsprite].cstat |= ESpriteFlags::FromInt(sc.Number); - } - } - } - else if (sc.Compare("lotag")) - { - if (sc.CheckNumber()) - { - if (currentwall != -1 && validateWall()) - { - wall[currentwall].lotag = sc.Number; - } - else if (currentsprite != -1 && validateSprite()) - { - sprites.sprites[currentsprite].lotag = sc.Number; - } - } - } - else if (sc.Compare("sw_serp_continue")) // This is a hack for SW's Last Warrior mod to continue from L4 to L5. - { - if (currentLevel) currentLevel->gameflags |= LEVEL_SW_DEATHEXIT_SERPENT_NEXT; - } + if (sc.Compare("sprite")) + { + currentwall = -1; + currentsector = -1; + if (sc.CheckNumber()) + { + currentsprite = sc.Number; + if ((unsigned)currentsprite >= sprites.sprites.Size()) + { + sc.ScriptMessage("Invalid sprite number %d", currentsprite); + currentsprite = -1; + } + } + else currentsprite = -1; + } + if (sc.Compare("wall")) + { + currentsprite = -1; + currentsector = -1; + if (sc.CheckNumber()) + { + currentwall = sc.Number; + if (!validWallIndex(currentwall)) + { + sc.ScriptMessage("Invalid wall number %d", currentwall); + currentwall = -1; + } + } + else currentwall = -1; + } + if (sc.Compare("sector")) + { + currentsprite = -1; + currentwall = -1; + if (sc.CheckNumber()) + { + currentsector = sc.Number; + if (!validSectorIndex(currentsector)) + { + sc.ScriptMessage("Invalid sector number %d", currentsector); + currentsector = -1; + } + } + else currentsector = -1; + } + else if (sc.Compare("sector")) + { + if (sc.CheckNumber()) + { + if (currentsprite != -1 && validateSprite()) + { + sprites.sprites[currentsprite].setsector(sc.Number); + } + } + } + else if (sc.Compare("picnum")) + { + if (sc.CheckNumber()) + { + if (currentwall != -1 && validateWall()) + { + wall[currentwall].picnum = sc.Number; + } + else if (currentsprite != -1 && validateSprite()) + { + sprites.sprites[currentsprite].picnum = sc.Number; + } + } + } + else if (sc.Compare("overpicnum")) + { + if (sc.CheckNumber() && validateWall()) + { + wall[currentwall].overpicnum = sc.Number; + } + } + else if (sc.Compare("overpicnum")) + { + if (sc.CheckNumber() && validateWall()) + { + wall[currentwall].overpicnum = sc.Number; + } + } + else if (sc.Compare("split")) + { + int start = -1, end = -1; + if (sc.CheckNumber()) start = sc.Number; + if (sc.CheckNumber()) end = sc.Number; + if (end >= 0 && validateSector()) + { + hw_SetSplitSector(currentsector, start, end); + } + } + else if (sc.Compare("clearflags")) + { + if (currentsector != -1 && validateSector()) + { + sc.GetString(); + if (sc.Compare("floor") && sc.CheckNumber()) + { + sector[currentsector].floorstat &= ESectorFlags::FromInt(~sc.Number); + } + else if (sc.Compare("ceiling") && sc.CheckNumber()) + { + sector[currentsector].ceilingstat &= ESectorFlags::FromInt(~sc.Number); + } + else sc.ScriptError("Bad token %s", sc.String); + } + else if (sc.CheckNumber()) + { + if (currentwall != -1 && validateWall()) + { + wall[currentwall].cstat &= EWallFlags::FromInt(~sc.Number); + } + else if (currentsprite != -1 && validateSprite()) + { + sprites.sprites[currentsprite].cstat &= ESpriteFlags::FromInt(~sc.Number); + } + } + } + else if (sc.Compare("setflags")) + { + if (sc.CheckNumber()) + { + if (currentwall != -1 && validateWall()) + { + wall[currentwall].cstat |= EWallFlags::FromInt(sc.Number); + } + else if (currentsprite != -1 && validateSprite()) + { + sprites.sprites[currentsprite].cstat |= ESpriteFlags::FromInt(sc.Number); + } + } + } + else if (sc.Compare("lotag")) + { + if (sc.CheckNumber()) + { + if (currentwall != -1 && validateWall()) + { + wall[currentwall].lotag = sc.Number; + } + else if (currentsprite != -1 && validateSprite()) + { + sprites.sprites[currentsprite].lotag = sc.Number; + } + } + } + else if (sc.Compare("sw_serp_continue")) // This is a hack for SW's Last Warrior mod to continue from L4 to L5. + { + if (currentLevel) currentLevel->gameflags |= LEVEL_SW_DEATHEXIT_SERPENT_NEXT; + } - else if (sc.Compare("angleoff") || sc.Compare("angoff")) - { - if (sc.CheckNumber() && validateSprite()) - sprites.sprext[currentsprite].angoff = (int16_t)sc.Number; - } - else if (sc.Compare("notmd") || sc.Compare("notmd2") || sc.Compare("notmd3")) - { - if (validateSprite()) - sprites.sprext[currentsprite].flags |= SPREXT_NOTMD; - } - else if (sc.Compare("nomdanim") || sc.Compare("nomd2anim") || sc.Compare("nomd3anim")) - { - if (validateSprite()) - sprites.sprext[currentsprite].flags |= SPREXT_NOMDANIM; - } - else if (sc.Compare("pitch")) - { - if (sc.CheckNumber() && validateSprite()) - sprites.sprext[currentsprite].pitch = (int16_t)sc.Number; - } - else if (sc.Compare("roll")) - { - if (sc.CheckNumber() && validateSprite()) - sprites.sprext[currentsprite].roll = (int16_t)sc.Number; - } - else if (sc.Compare("mdxoff") || sc.Compare("mdpivxoff") || sc.Compare("mdpivotxoff")) - { - if (sc.CheckNumber() && validateSprite()) - sprites.sprext[currentsprite].pivot_offset.X = sc.Number; - } - else if (sc.Compare("mdyoff") || sc.Compare("mdpivyoff") || sc.Compare("mdpivotyoff")) - { - if (sc.CheckNumber() && validateSprite()) - sprites.sprext[currentsprite].pivot_offset.Y = sc.Number; - } - else if (sc.Compare("mdzoff") || sc.Compare("mdpivzoff") || sc.Compare("mdpivotzoff")) - { - if (sc.CheckNumber() && validateSprite()) - sprites.sprext[currentsprite].pivot_offset.Z = sc.Number; - } - else if (sc.Compare("mdposxoff") || sc.Compare("mdpositionxoff")) - { - if (sc.CheckNumber() && validateSprite()) - sprites.sprext[currentsprite].position_offset.X = sc.Number; - } - else if (sc.Compare("mdposyoff") || sc.Compare("mdpositionyoff")) - { - if (sc.CheckNumber() && validateSprite()) - sprites.sprext[currentsprite].position_offset.X = sc.Number; - } - else if (sc.Compare("mdposzoff") || sc.Compare("mdpositionzoff")) - { - if (sc.CheckNumber() && validateSprite()) - sprites.sprext[currentsprite].position_offset.X = sc.Number; - } - else if (sc.Compare("away1")) - { - if (validateSprite()) - sprites.sprext[currentsprite].flags |= SPREXT_AWAY1; - } - else if (sc.Compare("away2")) - { - if (validateSprite()) - sprites.sprext[currentsprite].flags |= SPREXT_AWAY2; - } - else if (sc.Compare("mhkreset")) - { - if (validateSprite()) - { - auto& sx = sprites.sprext[currentsprite]; - sx.angoff = 0; - sx.flags &= ~(SPREXT_NOTMD | SPREXT_NOMDANIM | SPREXT_AWAY1 | SPREXT_AWAY2); - sx.pitch = 0; - sx.roll = 0; - sx.pivot_offset = {}; - sx.position_offset = {}; - } - } - else if (sc.Compare("light")) - { - // skip over it - once lights are working this should be reactivated. Assignments were kept as documentation. - sc.MustGetNumber(); - //light.sector= sc.Number; - sc.MustGetNumber(); - //light.x= sc.Number; - sc.MustGetNumber(); - //light.y= sc.Number; - sc.MustGetNumber(); - //light.z= sc.Number; - sc.MustGetNumber(); - //light.range= sc.Number; - sc.MustGetNumber(); - //light.color[0]= sc.Number; - sc.MustGetNumber(); - //light.color[1]= sc.Number; - sc.MustGetNumber(); - //light.color[2]= sc.Number; - sc.MustGetNumber(); - //light.radius= sc.Number; - sc.MustGetNumber(); - //light.faderadius= sc.Number; - sc.MustGetNumber(); - //light.angle= sc.Number; - sc.MustGetNumber(); - //light.horiz= sc.Number; - sc.MustGetNumber(); - //light.minshade= sc.Number; - sc.MustGetNumber(); - //light.maxshade= sc.Number; - sc.MustGetNumber(); - //light.priority= sc.Number; - sc.MustGetString(); - //light.tilenum= sc.Number; - } - } + else if (sc.Compare("angleoff") || sc.Compare("angoff")) + { + if (sc.CheckNumber() && validateSprite()) + sprites.sprext[currentsprite].angoff = (int16_t)sc.Number; + } + else if (sc.Compare("notmd") || sc.Compare("notmd2") || sc.Compare("notmd3")) + { + if (validateSprite()) + sprites.sprext[currentsprite].flags |= SPREXT_NOTMD; + } + else if (sc.Compare("nomdanim") || sc.Compare("nomd2anim") || sc.Compare("nomd3anim")) + { + if (validateSprite()) + sprites.sprext[currentsprite].flags |= SPREXT_NOMDANIM; + } + else if (sc.Compare("pitch")) + { + if (sc.CheckNumber() && validateSprite()) + sprites.sprext[currentsprite].pitch = (int16_t)sc.Number; + } + else if (sc.Compare("roll")) + { + if (sc.CheckNumber() && validateSprite()) + sprites.sprext[currentsprite].roll = (int16_t)sc.Number; + } + else if (sc.Compare("mdxoff") || sc.Compare("mdpivxoff") || sc.Compare("mdpivotxoff")) + { + if (sc.CheckNumber() && validateSprite()) + sprites.sprext[currentsprite].pivot_offset.X = sc.Number; + } + else if (sc.Compare("mdyoff") || sc.Compare("mdpivyoff") || sc.Compare("mdpivotyoff")) + { + if (sc.CheckNumber() && validateSprite()) + sprites.sprext[currentsprite].pivot_offset.Y = sc.Number; + } + else if (sc.Compare("mdzoff") || sc.Compare("mdpivzoff") || sc.Compare("mdpivotzoff")) + { + if (sc.CheckNumber() && validateSprite()) + sprites.sprext[currentsprite].pivot_offset.Z = sc.Number; + } + else if (sc.Compare("mdposxoff") || sc.Compare("mdpositionxoff")) + { + if (sc.CheckNumber() && validateSprite()) + sprites.sprext[currentsprite].position_offset.X = sc.Number; + } + else if (sc.Compare("mdposyoff") || sc.Compare("mdpositionyoff")) + { + if (sc.CheckNumber() && validateSprite()) + sprites.sprext[currentsprite].position_offset.X = sc.Number; + } + else if (sc.Compare("mdposzoff") || sc.Compare("mdpositionzoff")) + { + if (sc.CheckNumber() && validateSprite()) + sprites.sprext[currentsprite].position_offset.X = sc.Number; + } + else if (sc.Compare("away1")) + { + if (validateSprite()) + sprites.sprext[currentsprite].flags |= SPREXT_AWAY1; + } + else if (sc.Compare("away2")) + { + if (validateSprite()) + sprites.sprext[currentsprite].flags |= SPREXT_AWAY2; + } + else if (sc.Compare("mhkreset")) + { + if (validateSprite()) + { + auto& sx = sprites.sprext[currentsprite]; + sx.angoff = 0; + sx.flags &= ~(SPREXT_NOTMD | SPREXT_NOMDANIM | SPREXT_AWAY1 | SPREXT_AWAY2); + sx.pitch = 0; + sx.roll = 0; + sx.pivot_offset = {}; + sx.position_offset = {}; + } + } + else if (sc.Compare("light")) + { + // skip over it - once lights are working this should be reactivated. Assignments were kept as documentation. + sc.MustGetNumber(); + //light.sector= sc.Number; + sc.MustGetNumber(); + //light.x= sc.Number; + sc.MustGetNumber(); + //light.y= sc.Number; + sc.MustGetNumber(); + //light.z= sc.Number; + sc.MustGetNumber(); + //light.range= sc.Number; + sc.MustGetNumber(); + //light.color[0]= sc.Number; + sc.MustGetNumber(); + //light.color[1]= sc.Number; + sc.MustGetNumber(); + //light.color[2]= sc.Number; + sc.MustGetNumber(); + //light.radius= sc.Number; + sc.MustGetNumber(); + //light.faderadius= sc.Number; + sc.MustGetNumber(); + //light.angle= sc.Number; + sc.MustGetNumber(); + //light.horiz= sc.Number; + sc.MustGetNumber(); + //light.minshade= sc.Number; + sc.MustGetNumber(); + //light.maxshade= sc.Number; + sc.MustGetNumber(); + //light.priority= sc.Number; + sc.MustGetString(); + //light.tilenum= sc.Number; + } + } return 0; } void loadMapHack(const char* filename, const unsigned char* md4, SpawnSpriteDef& sprites) { - hw_ClearSplitSector(); + hw_ClearSplitSector(); - FString internal = "engine/compatibility/"; - for (int j = 0; j < 16; ++j) - { - internal.AppendFormat("%02x", md4[j]); - } - LoadMapHack(internal + ".mhk", sprites); - FString hack = StripExtension(filename) + ".mhk"; + FString internal = "engine/compatibility/"; + for (int j = 0; j < 16; ++j) + { + internal.AppendFormat("%02x", md4[j]); + } + LoadMapHack(internal + ".mhk", sprites); + FString hack = StripExtension(filename) + ".mhk"; - if (LoadMapHack(hack, sprites)) - { - for (auto& mhk : usermaphacks) - { - if (!memcmp(md4, mhk.md4, 16)) - { - LoadMapHack(mhk.mhkfile, sprites); - } - } - } + if (LoadMapHack(hack, sprites)) + { + for (auto& mhk : usermaphacks) + { + if (!memcmp(md4, mhk.md4, 16)) + { + LoadMapHack(mhk.mhkfile, sprites); + } + } + } } // Map hacks use MD4 instead of MD5. Oh, well... CCMD(md4sum) { - if (argv.argc() < 2) - { - Printf("Usage: md4sum ...\n"); - } - for (int i = 1; i < argv.argc(); ++i) - { - FileReader fr = fileSystem.OpenFileReader(argv[i]); - if (!fr.isOpen()) - { - Printf("%s: %s\n", argv[i], strerror(errno)); - } - else - { - auto data = fr.Read(); - uint8_t digest[16]; - md4once(data.Data(), data.Size(), digest); - for (int j = 0; j < 16; ++j) - { - Printf("%02x", digest[j]); - } - Printf(" //*%s\n", argv[i]); - } - } + if (argv.argc() < 2) + { + Printf("Usage: md4sum ...\n"); + } + for (int i = 1; i < argv.argc(); ++i) + { + FileReader fr = fileSystem.OpenFileReader(argv[i]); + if (!fr.isOpen()) + { + Printf("%s: %s\n", argv[i], strerror(errno)); + } + else + { + auto data = fr.Read(); + uint8_t digest[16]; + md4once(data.Data(), data.Size(), digest); + for (int j = 0; j < 16; ++j) + { + Printf("%02x", digest[j]); + } + Printf(" //*%s\n", argv[i]); + } + } } diff --git a/source/games/blood/src/aiunicult.cpp b/source/games/blood/src/aiunicult.cpp index 6c581bb56..170eed264 100644 --- a/source/games/blood/src/aiunicult.cpp +++ b/source/games/blood/src/aiunicult.cpp @@ -90,23 +90,23 @@ AISTATE genDudePunch = { kAiStateChase,10, nGenDudePunch, 0, NULL, NULL, forcePu // --------------------- const GENDUDESND gCustomDudeSnd[] = { - { 1003, 2, 0, true, false }, // spot sound - { 1013, 2, 2, true, true }, // pain sound - { 1018, 2, 4, false, true }, // death sound - { 1031, 2, 6, true, true }, // burning state sound - { 1018, 2, 8, false, true }, // explosive death or end of burning state sound - { 4021, 2, 10, true, false }, // target of dude is dead - { 1005, 2, 12, true, false }, // chase sound - { -1, 0, 14, false, true }, // weapon attack - { -1, 0, 15, false, true }, // throw attack - { -1, 0, 16, false, true }, // melee attack - { 9008, 0, 17, false, false }, // transforming in other dude + { 1003, 2, 0, true, false }, // spot sound + { 1013, 2, 2, true, true }, // pain sound + { 1018, 2, 4, false, true }, // death sound + { 1031, 2, 6, true, true }, // burning state sound + { 1018, 2, 8, false, true }, // explosive death or end of burning state sound + { 4021, 2, 10, true, false }, // target of dude is dead + { 1005, 2, 12, true, false }, // chase sound + { -1, 0, 14, false, true }, // weapon attack + { -1, 0, 15, false, true }, // throw attack + { -1, 0, 16, false, true }, // melee attack + { 9008, 0, 17, false, false }, // transforming in other dude }; // for kModernThingThrowableRock const int16_t gCustomDudeDebrisPics[6] = { - - 2406, 2280, 2185, 2155, 2620, 3135 + + 2406, 2280, 2185, 2155, 2620, 3135 }; @@ -118,8 +118,8 @@ const int16_t gCustomDudeDebrisPics[6] = { static void forcePunch(DBloodActor* actor) { - if (actor->genDudeExtra.forcePunch && seqGetStatus(actor) == -1) - punchCallback(0, actor); + if (actor->genDudeExtra.forcePunch && seqGetStatus(actor) == -1) + punchCallback(0, actor); } //--------------------------------------------------------------------------- @@ -130,39 +130,39 @@ static void forcePunch(DBloodActor* actor) static bool genDudeAdjustSlope(DBloodActor* actor, int dist, int weaponType, int by = 64) { - if (actor->GetTarget() != nullptr) - { - int fStart = 0; - int fEnd = 0; - GENDUDEEXTRA* pExtra = &actor->genDudeExtra; - unsigned int clipMask = (weaponType == kGenDudeWeaponMissile) ? CLIPMASK0 : CLIPMASK1; + if (actor->GetTarget() != nullptr) + { + int fStart = 0; + int fEnd = 0; + GENDUDEEXTRA* pExtra = &actor->genDudeExtra; + unsigned int clipMask = (weaponType == kGenDudeWeaponMissile) ? CLIPMASK0 : CLIPMASK1; - for (int i = -8191; i < 8192; i += by) - { - HitScan(actor, actor->spr.pos.Z, bcos(actor->spr.ang), bsin(actor->spr.ang), i, clipMask, dist); - if (!fStart && actor->GetTarget() == gHitInfo.actor()) fStart = i; - else if (fStart && actor->GetTarget() != gHitInfo.actor()) - { - fEnd = i; - break; - } - } + for (int i = -8191; i < 8192; i += by) + { + HitScan(actor, actor->spr.pos.Z, bcos(actor->spr.ang), bsin(actor->spr.ang), i, clipMask, dist); + if (!fStart && actor->GetTarget() == gHitInfo.actor()) fStart = i; + else if (fStart && actor->GetTarget() != gHitInfo.actor()) + { + fEnd = i; + break; + } + } - if (fStart != fEnd) - { - if (weaponType == kGenDudeWeaponHitscan) - { - actor->dudeSlope = fStart - ((fStart - fEnd) >> 2); - } - else if (weaponType == kGenDudeWeaponMissile) - { - const MissileType* pMissile = &missileInfo[pExtra->curWeapon - kMissileBase]; - actor->dudeSlope = (fStart - ((fStart - fEnd) >> 2)) - (pMissile->clipDist << 1); - } - return true; - } - } - return false; + if (fStart != fEnd) + { + if (weaponType == kGenDudeWeaponHitscan) + { + actor->dudeSlope = fStart - ((fStart - fEnd) >> 2); + } + else if (weaponType == kGenDudeWeaponMissile) + { + const MissileType* pMissile = &missileInfo[pExtra->curWeapon - kMissileBase]; + actor->dudeSlope = (fStart - ((fStart - fEnd) >> 2)) - (pMissile->clipDist << 1); + } + return true; + } + } + return false; } @@ -174,10 +174,10 @@ static bool genDudeAdjustSlope(DBloodActor* actor, int dist, int weaponType, int void genDudeUpdate(DBloodActor* actor) { - GENDUDEEXTRA* pExtra = &actor->genDudeExtra; - for (int i = 0; i < kGenDudePropertyMax; i++) { - if (pExtra->updReq[i]) genDudePrepare(actor, i); - } + GENDUDEEXTRA* pExtra = &actor->genDudeExtra; + for (int i = 0; i < kGenDudePropertyMax; i++) { + if (pExtra->updReq[i]) genDudePrepare(actor, i); + } } //--------------------------------------------------------------------------- @@ -188,25 +188,25 @@ void genDudeUpdate(DBloodActor* actor) void punchCallback(int, DBloodActor* actor) { - auto const target = actor->GetTarget(); - if (target != nullptr) - { - int nZOffset1 = getDudeInfo(actor->spr.type)->eyeHeight * actor->spr.yrepeat << 2; - int nZOffset2 = 0; - + auto const target = actor->GetTarget(); + if (target != nullptr) + { + int nZOffset1 = getDudeInfo(actor->spr.type)->eyeHeight * actor->spr.yrepeat << 2; + int nZOffset2 = 0; - if(target->IsDudeActor()) - nZOffset2 = getDudeInfo(target->spr.type)->eyeHeight * target->spr.yrepeat << 2; - int dx = bcos(actor->spr.ang); - int dy = bsin(actor->spr.ang); - int dz = nZOffset1 - nZOffset2; + if (target->IsDudeActor()) + nZOffset2 = getDudeInfo(target->spr.type)->eyeHeight * target->spr.yrepeat << 2; - if (!playGenDudeSound(actor, kGenDudeSndAttackMelee)) - sfxPlay3DSound(actor, 530, 1, 0); + int dx = bcos(actor->spr.ang); + int dy = bsin(actor->spr.ang); + int dz = nZOffset1 - nZOffset2; - actFireVector(actor, 0, 0, dx, dy, dz,kVectorGenDudePunch); - } + if (!playGenDudeSound(actor, kGenDudeSndAttackMelee)) + sfxPlay3DSound(actor, 530, 1, 0); + + actFireVector(actor, 0, 0, dx, dy, dz, kVectorGenDudePunch); + } } //--------------------------------------------------------------------------- @@ -217,64 +217,64 @@ void punchCallback(int, DBloodActor* actor) void genDudeAttack1(int, DBloodActor* actor) { - if (actor->GetTarget() == nullptr) return; + if (actor->GetTarget() == nullptr) return; - int dx, dy, dz; - actor->xvel = actor->yvel = 0; - - GENDUDEEXTRA* pExtra = &actor->genDudeExtra; - int dispersion = pExtra->baseDispersion; - if (inDuck(actor->xspr.aiState)) - dispersion = ClipLow(dispersion >> 1, kGenDudeMinDispesion); + int dx, dy, dz; + actor->xvel = actor->yvel = 0; - if (pExtra->weaponType == kGenDudeWeaponHitscan) - { - dx = bcos(actor->spr.ang); dy = bsin(actor->spr.ang); dz = actor->dudeSlope; - // dispersal modifiers here in case if non-melee enemy - if (!dudeIsMelee(actor)) - { - dx += Random3(dispersion); dy += Random3(dispersion); dz += Random3(dispersion); - } + GENDUDEEXTRA* pExtra = &actor->genDudeExtra; + int dispersion = pExtra->baseDispersion; + if (inDuck(actor->xspr.aiState)) + dispersion = ClipLow(dispersion >> 1, kGenDudeMinDispesion); - actFireVector(actor, 0, 0, dx, dy, dz,(VECTOR_TYPE)pExtra->curWeapon); - if (!playGenDudeSound(actor, kGenDudeSndAttackNormal)) - sfxPlayVectorSound(actor, pExtra->curWeapon); - } - else if (pExtra->weaponType == kGenDudeWeaponSummon) - { - DBloodActor* spawned = nullptr; - int dist = actor->spr.clipdist << 4; - if (pExtra->slaveCount <= gGameOptions.nDifficulty) - { - if ((spawned = actSpawnDude(actor, pExtra->curWeapon, dist + Random(dist), 0)) != NULL) - { - spawned->SetOwner(actor); + if (pExtra->weaponType == kGenDudeWeaponHitscan) + { + dx = bcos(actor->spr.ang); dy = bsin(actor->spr.ang); dz = actor->dudeSlope; + // dispersal modifiers here in case if non-melee enemy + if (!dudeIsMelee(actor)) + { + dx += Random3(dispersion); dy += Random3(dispersion); dz += Random3(dispersion); + } - if (spawned->hasX()) - { - spawned->SetTarget(actor->GetTarget()); - if (spawned->GetTarget() != nullptr) - aiActivateDude(spawned); - } + actFireVector(actor, 0, 0, dx, dy, dz, (VECTOR_TYPE)pExtra->curWeapon); + if (!playGenDudeSound(actor, kGenDudeSndAttackNormal)) + sfxPlayVectorSound(actor, pExtra->curWeapon); + } + else if (pExtra->weaponType == kGenDudeWeaponSummon) + { + DBloodActor* spawned = nullptr; + int dist = actor->spr.clipdist << 4; + if (pExtra->slaveCount <= gGameOptions.nDifficulty) + { + if ((spawned = actSpawnDude(actor, pExtra->curWeapon, dist + Random(dist), 0)) != NULL) + { + spawned->SetOwner(actor); - gKillMgr.AddNewKill(1); - pExtra->slave[pExtra->slaveCount++] = spawned; - if (!playGenDudeSound(actor, kGenDudeSndAttackNormal)) - sfxPlay3DSoundCP(actor, 379, 1, 0, 0x10000 - Random3(0x3000)); - } - } - } - else if (pExtra->weaponType == kGenDudeWeaponMissile) - { - dx = bcos(actor->spr.ang); dy = bsin(actor->spr.ang); dz = actor->dudeSlope; + if (spawned->hasX()) + { + spawned->SetTarget(actor->GetTarget()); + if (spawned->GetTarget() != nullptr) + aiActivateDude(spawned); + } - // dispersal modifiers here - dx += Random3(dispersion); dy += Random3(dispersion); dz += Random3(dispersion >> 1); + gKillMgr.AddNewKill(1); + pExtra->slave[pExtra->slaveCount++] = spawned; + if (!playGenDudeSound(actor, kGenDudeSndAttackNormal)) + sfxPlay3DSoundCP(actor, 379, 1, 0, 0x10000 - Random3(0x3000)); + } + } + } + else if (pExtra->weaponType == kGenDudeWeaponMissile) + { + dx = bcos(actor->spr.ang); dy = bsin(actor->spr.ang); dz = actor->dudeSlope; - actFireMissile(actor, 0, 0, dx, dy, dz, pExtra->curWeapon); - if (!playGenDudeSound(actor, kGenDudeSndAttackNormal)) - sfxPlayMissileSound(actor, pExtra->curWeapon); - } + // dispersal modifiers here + dx += Random3(dispersion); dy += Random3(dispersion); dz += Random3(dispersion >> 1); + + actFireMissile(actor, 0, 0, dx, dy, dz, pExtra->curWeapon); + if (!playGenDudeSound(actor, kGenDudeSndAttackNormal)) + sfxPlayMissileSound(actor, pExtra->curWeapon); + } } //--------------------------------------------------------------------------- @@ -285,110 +285,110 @@ void genDudeAttack1(int, DBloodActor* actor) void ThrowCallback1(int, DBloodActor* actor) { - ThrowThing(actor, true); + ThrowThing(actor, true); } void ThrowCallback2(int, DBloodActor* actor) { - ThrowThing(actor, false); + ThrowThing(actor, false); } -static void ThrowThing(DBloodActor* actor, bool impact) +static void ThrowThing(DBloodActor* actor, bool impact) { - auto target = actor->GetTarget(); + auto target = actor->GetTarget(); - if (target == nullptr) - return; + if (target == nullptr) + return; - if (!(target->spr.type >= kDudeBase && target->spr.type < kDudeMax)) - return; + if (!(target->spr.type >= kDudeBase && target->spr.type < kDudeMax)) + return; - int curWeapon = actor->genDudeExtra.curWeapon; - int weaponType = actor->genDudeExtra.weaponType; - if (weaponType != kGenDudeWeaponThrow) return; + int curWeapon = actor->genDudeExtra.curWeapon; + int weaponType = actor->genDudeExtra.weaponType; + if (weaponType != kGenDudeWeaponThrow) return; - const THINGINFO* pThinkInfo = &thingInfo[curWeapon - kThingBase]; - if (!gThingInfoExtra[curWeapon - kThingBase].allowThrow) return; - else if (!playGenDudeSound(actor, kGenDudeSndAttackThrow)) - sfxPlay3DSound(actor, 455, -1, 0); - - int zThrow = 14500; - int dx = target->spr.pos.X - actor->spr.pos.X; - int dy = target->spr.pos.Y - actor->spr.pos.Y; - int dz = target->spr.pos.Z - actor->spr.pos.Z; - int dist = approxDist(dx, dy); - - auto actLeech = leechIsDropped(actor); - - switch (curWeapon) { - case kModernThingEnemyLifeLeech: - case kThingDroppedLifeLeech: - zThrow = 5000; - // pickup life leech before throw it again - if (actLeech != NULL) removeLeech(actLeech); - break; - } + const THINGINFO* pThinkInfo = &thingInfo[curWeapon - kThingBase]; + if (!gThingInfoExtra[curWeapon - kThingBase].allowThrow) return; + else if (!playGenDudeSound(actor, kGenDudeSndAttackThrow)) + sfxPlay3DSound(actor, 455, -1, 0); - DBloodActor* spawned = nullptr; - if ((spawned = actFireThing(actor, 0, 0, (dz / 128) - zThrow, curWeapon, DivScale(dist / 540, 120, 23))) == nullptr) return; - - if (pThinkInfo->picnum < 0 && spawned->spr.type != kModernThingThrowableRock) spawned->spr.picnum = 0; - - spawned->SetOwner(actor); + int zThrow = 14500; + int dx = target->spr.pos.X - actor->spr.pos.X; + int dy = target->spr.pos.Y - actor->spr.pos.Y; + int dz = target->spr.pos.Z - actor->spr.pos.Z; + int dist = approxDist(dx, dy); - switch (curWeapon) { - case kThingNapalmBall: - spawned->spr.xrepeat = spawned->spr.yrepeat = 24; - spawned->xspr.data4 = 3 + gGameOptions.nDifficulty; - impact = true; - break; - case kModernThingThrowableRock: - spawned->spr.picnum = gCustomDudeDebrisPics[Random(5)]; - spawned->spr.xrepeat = spawned->spr.yrepeat = 24 + Random(42); - spawned->spr.cstat |= CSTAT_SPRITE_BLOCK; - spawned->spr.pal = 5; + auto actLeech = leechIsDropped(actor); - if (Chance(0x5000)) spawned->spr.cstat |= CSTAT_SPRITE_XFLIP; - if (Chance(0x5000)) spawned->spr.cstat |= CSTAT_SPRITE_YFLIP; + switch (curWeapon) { + case kModernThingEnemyLifeLeech: + case kThingDroppedLifeLeech: + zThrow = 5000; + // pickup life leech before throw it again + if (actLeech != NULL) removeLeech(actLeech); + break; + } - if (spawned->spr.xrepeat > 60) spawned->xspr.data1 = 43; - else if (spawned->spr.xrepeat > 40) spawned->xspr.data1 = 33; - else if (spawned->spr.xrepeat > 30) spawned->xspr.data1 = 23; - else spawned->xspr.data1 = 12; - return; - case kThingTNTBarrel: - case kThingArmedProxBomb: - case kThingArmedSpray: - impact = false; - break; - case kModernThingTNTProx: - spawned->xspr.state = 0; - spawned->xspr.Proximity = true; - return; - case kModernThingEnemyLifeLeech: - if (actLeech != nullptr) spawned->xspr.health = actLeech->xspr.health; - else spawned->xspr.health = ((pThinkInfo->startHealth << 4) * gGameOptions.nDifficulty) >> 1; + DBloodActor* spawned = nullptr; + if ((spawned = actFireThing(actor, 0, 0, (dz / 128) - zThrow, curWeapon, DivScale(dist / 540, 120, 23))) == nullptr) return; - sfxPlay3DSound(actor, 490, -1, 0); + if (pThinkInfo->picnum < 0 && spawned->spr.type != kModernThingThrowableRock) spawned->spr.picnum = 0; - spawned->xspr.data3 = 512 / (gGameOptions.nDifficulty + 1); - spawned->spr.cstat &= ~CSTAT_SPRITE_BLOCK; - spawned->spr.pal = 6; - spawned->spr.clipdist = 0; - spawned->SetTarget(actor->GetTarget()); - spawned->xspr.Proximity = true; - spawned->xspr.stateTimer = 1; - - actor->genDudeExtra.pLifeLeech = spawned; - evPostActor(spawned, 80, kCallbackLeechStateTimer); - return; - } + spawned->SetOwner(actor); - if (impact == true && dist <= 7680) spawned->xspr.Impact = true; - else { - spawned->xspr.Impact = false; - evPostActor(spawned, 120 * Random(2) + 120, kCmdOn); - } + switch (curWeapon) { + case kThingNapalmBall: + spawned->spr.xrepeat = spawned->spr.yrepeat = 24; + spawned->xspr.data4 = 3 + gGameOptions.nDifficulty; + impact = true; + break; + case kModernThingThrowableRock: + spawned->spr.picnum = gCustomDudeDebrisPics[Random(5)]; + spawned->spr.xrepeat = spawned->spr.yrepeat = 24 + Random(42); + spawned->spr.cstat |= CSTAT_SPRITE_BLOCK; + spawned->spr.pal = 5; + + if (Chance(0x5000)) spawned->spr.cstat |= CSTAT_SPRITE_XFLIP; + if (Chance(0x5000)) spawned->spr.cstat |= CSTAT_SPRITE_YFLIP; + + if (spawned->spr.xrepeat > 60) spawned->xspr.data1 = 43; + else if (spawned->spr.xrepeat > 40) spawned->xspr.data1 = 33; + else if (spawned->spr.xrepeat > 30) spawned->xspr.data1 = 23; + else spawned->xspr.data1 = 12; + return; + case kThingTNTBarrel: + case kThingArmedProxBomb: + case kThingArmedSpray: + impact = false; + break; + case kModernThingTNTProx: + spawned->xspr.state = 0; + spawned->xspr.Proximity = true; + return; + case kModernThingEnemyLifeLeech: + if (actLeech != nullptr) spawned->xspr.health = actLeech->xspr.health; + else spawned->xspr.health = ((pThinkInfo->startHealth << 4) * gGameOptions.nDifficulty) >> 1; + + sfxPlay3DSound(actor, 490, -1, 0); + + spawned->xspr.data3 = 512 / (gGameOptions.nDifficulty + 1); + spawned->spr.cstat &= ~CSTAT_SPRITE_BLOCK; + spawned->spr.pal = 6; + spawned->spr.clipdist = 0; + spawned->SetTarget(actor->GetTarget()); + spawned->xspr.Proximity = true; + spawned->xspr.stateTimer = 1; + + actor->genDudeExtra.pLifeLeech = spawned; + evPostActor(spawned, 80, kCallbackLeechStateTimer); + return; + } + + if (impact == true && dist <= 7680) spawned->xspr.Impact = true; + else { + spawned->xspr.Impact = false; + evPostActor(spawned, 120 * Random(2) + 120, kCmdOn); + } } //--------------------------------------------------------------------------- @@ -399,10 +399,10 @@ static void ThrowThing(DBloodActor* actor, bool impact) static void unicultThinkSearch(DBloodActor* actor) { - // TO DO: if can't see the target, but in fireDist range - stop moving and look around - - aiChooseDirection(actor,actor->xspr.goalAng); - aiLookForTarget(actor); + // TO DO: if can't see the target, but in fireDist range - stop moving and look around + + aiChooseDirection(actor, actor->xspr.goalAng); + aiLookForTarget(actor); } //--------------------------------------------------------------------------- @@ -413,25 +413,25 @@ static void unicultThinkSearch(DBloodActor* actor) static void unicultThinkGoto(DBloodActor* actor) { - if (!(actor->spr.type >= kDudeBase && actor->spr.type < kDudeMax)) - { - Printf(PRINT_HIGH, "actor->spr.type >= kDudeBase && actor->spr.type < kDudeMax"); - return; - } + if (!(actor->spr.type >= kDudeBase && actor->spr.type < kDudeMax)) + { + Printf(PRINT_HIGH, "actor->spr.type >= kDudeBase && actor->spr.type < kDudeMax"); + return; + } - int dx = actor->xspr.targetX - actor->spr.pos.X; - int dy = actor->xspr.targetY - actor->spr.pos.Y; - int nAngle = getangle(dx, dy); + int dx = actor->xspr.targetX - actor->spr.pos.X; + int dy = actor->xspr.targetY - actor->spr.pos.Y; + int nAngle = getangle(dx, dy); - aiChooseDirection(actor,nAngle); + aiChooseDirection(actor, nAngle); - // if reached target, change to search mode - if (approxDist(dx, dy) < 5120 && abs(actor->spr.ang - nAngle) < getDudeInfo(actor->spr.type)->periphery) - { - if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeSearchW); - else aiGenDudeNewState(actor, &genDudeSearchL); - } - aiThinkTarget(actor); + // if reached target, change to search mode + if (approxDist(dx, dy) < 5120 && abs(actor->spr.ang - nAngle) < getDudeInfo(actor->spr.type)->periphery) + { + if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeSearchW); + else aiGenDudeNewState(actor, &genDudeSearchL); + } + aiThinkTarget(actor); } //--------------------------------------------------------------------------- @@ -442,592 +442,593 @@ static void unicultThinkGoto(DBloodActor* actor) static void unicultThinkChase(DBloodActor* actor) { - if (actor->spr.type < kDudeBase || actor->spr.type >= kDudeMax) return; + if (actor->spr.type < kDudeBase || actor->spr.type >= kDudeMax) return; - auto const target = actor->GetTarget(); - if (target == nullptr) - { - if(spriteIsUnderwater(actor,false)) aiGenDudeNewState(actor, &genDudeGotoW); - else aiGenDudeNewState(actor, &genDudeGotoL); - return; - } - else - { - genDudeUpdate(actor); - } + auto const target = actor->GetTarget(); + if (target == nullptr) + { + if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeGotoW); + else aiGenDudeNewState(actor, &genDudeGotoL); + return; + } + else + { + genDudeUpdate(actor); + } - if (!target || !target->IsDudeActor() || !target->hasX()) // target lost - { - if(spriteIsUnderwater(actor,false)) aiGenDudeNewState(actor, &genDudeSearchShortW); - else aiGenDudeNewState(actor, &genDudeSearchShortL); - actor->SetTarget(nullptr); - return; - } + if (!target || !target->IsDudeActor() || !target->hasX()) // target lost + { + if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeSearchShortW); + else aiGenDudeNewState(actor, &genDudeSearchShortL); + actor->SetTarget(nullptr); + return; + } - if (target->xspr.health <= 0) // target is dead - { - PLAYER* pPlayer = NULL; - if ((!target->IsPlayerActor()) || ((pPlayer = getPlayerById(target->spr.type)) != NULL && pPlayer->fragger == actor)) - { - playGenDudeSound(actor, kGenDudeSndTargetDead); - if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeSearchShortW); - else aiGenDudeNewState(actor, &genDudeSearchShortL); - } - else if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeGotoW); - else aiGenDudeNewState(actor, &genDudeGotoL); - actor->SetTarget(nullptr); - return; - } - - // check target - int dx = target->spr.pos.X - actor->spr.pos.X; - int dy = target->spr.pos.Y - actor->spr.pos.Y; - int dist = ClipLow((int)approxDist(dx, dy), 1); + if (target->xspr.health <= 0) // target is dead + { + PLAYER* pPlayer = NULL; + if ((!target->IsPlayerActor()) || ((pPlayer = getPlayerById(target->spr.type)) != NULL && pPlayer->fragger == actor)) + { + playGenDudeSound(actor, kGenDudeSndTargetDead); + if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeSearchShortW); + else aiGenDudeNewState(actor, &genDudeSearchShortL); + } + else if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeGotoW); + else aiGenDudeNewState(actor, &genDudeGotoL); + actor->SetTarget(nullptr); + return; + } - // quick hack to prevent spinning around or changing attacker's sprite angle on high movement speeds - // when attacking the target. It happens because vanilla function takes in account x and y velocity, - // so i use fake velocity with fixed value and pass it as argument. - int xvelocity = actor->xvel; - int yvelocity = actor->yvel; - if (inAttack(actor->xspr.aiState)) - xvelocity = yvelocity = ClipLow(actor->spr.clipdist >> 1, 1); + // check target + int dx = target->spr.pos.X - actor->spr.pos.X; + int dy = target->spr.pos.Y - actor->spr.pos.Y; + int dist = ClipLow((int)approxDist(dx, dy), 1); - //aiChooseDirection(actor,getangle(dx, dy)); - aiGenDudeChooseDirection(actor, getangle(dx, dy), xvelocity, yvelocity); + // quick hack to prevent spinning around or changing attacker's sprite angle on high movement speeds + // when attacking the target. It happens because vanilla function takes in account x and y velocity, + // so i use fake velocity with fixed value and pass it as argument. + int xvelocity = actor->xvel; + int yvelocity = actor->yvel; + if (inAttack(actor->xspr.aiState)) + xvelocity = yvelocity = ClipLow(actor->spr.clipdist >> 1, 1); - GENDUDEEXTRA* pExtra = &actor->genDudeExtra; - if (!pExtra->canAttack) - { - if (pExtra->canWalk) aiSetTarget(actor, actor); // targeting self??? - if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeGotoW); - else aiGenDudeNewState(actor, &genDudeGotoL); - return; - } - else if (target->IsPlayerActor()) - { - PLAYER* pPlayer = &gPlayer[target->spr.type - kDudePlayer1]; - if (powerupCheck(pPlayer, kPwUpShadowCloak) > 0) - { - if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeSearchShortW); - else aiGenDudeNewState(actor, &genDudeSearchShortL); - actor->SetTarget(nullptr); - return; - } - } - - DUDEINFO* pDudeInfo = getDudeInfo(actor->spr.type); - int losAngle = ((getangle(dx, dy) + 1024 - actor->spr.ang) & 2047) - 1024; - int eyeAboveZ = (pDudeInfo->eyeHeight * actor->spr.yrepeat) << 2; + //aiChooseDirection(actor,getangle(dx, dy)); + aiGenDudeChooseDirection(actor, getangle(dx, dy), xvelocity, yvelocity); - if (dist > pDudeInfo->seeDist || !cansee(target->spr.pos.X, target->spr.pos.Y, target->spr.pos.Z, target->spr.sector(), - actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z - eyeAboveZ, actor->spr.sector())) - { - if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeSearchW); - else aiGenDudeNewState(actor, &genDudeSearchL); - actor->SetTarget(nullptr); - return; - } + GENDUDEEXTRA* pExtra = &actor->genDudeExtra; + if (!pExtra->canAttack) + { + if (pExtra->canWalk) aiSetTarget(actor, actor); // targeting self??? + if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeGotoW); + else aiGenDudeNewState(actor, &genDudeGotoL); + return; + } + else if (target->IsPlayerActor()) + { + PLAYER* pPlayer = &gPlayer[target->spr.type - kDudePlayer1]; + if (powerupCheck(pPlayer, kPwUpShadowCloak) > 0) + { + if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeSearchShortW); + else aiGenDudeNewState(actor, &genDudeSearchShortL); + actor->SetTarget(nullptr); + return; + } + } - // is the target visible? - if (dist < pDudeInfo->seeDist && abs(losAngle) <= pDudeInfo->periphery) { + DUDEINFO* pDudeInfo = getDudeInfo(actor->spr.type); + int losAngle = ((getangle(dx, dy) + 1024 - actor->spr.ang) & 2047) - 1024; + int eyeAboveZ = (pDudeInfo->eyeHeight * actor->spr.yrepeat) << 2; - if ((PlayClock & 64) == 0 && Chance(0x3000) && !spriteIsUnderwater(actor, false)) - playGenDudeSound(actor, kGenDudeSndChasing); + if (dist > pDudeInfo->seeDist || !cansee(target->spr.pos.X, target->spr.pos.Y, target->spr.pos.Z, target->spr.sector(), + actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z - eyeAboveZ, actor->spr.sector())) + { + if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeSearchW); + else aiGenDudeNewState(actor, &genDudeSearchL); + actor->SetTarget(nullptr); + return; + } - actor->dudeSlope = dist == 0 ? 0 : DivScale(target->spr.pos.Z - actor->spr.pos.Z, dist, 10); + // is the target visible? + if (dist < pDudeInfo->seeDist && abs(losAngle) <= pDudeInfo->periphery) { - int curWeapon = actor->genDudeExtra.curWeapon; - int weaponType = actor->genDudeExtra.weaponType; + if ((PlayClock & 64) == 0 && Chance(0x3000) && !spriteIsUnderwater(actor, false)) + playGenDudeSound(actor, kGenDudeSndChasing); - auto actLeech = leechIsDropped(actor); + actor->dudeSlope = dist == 0 ? 0 : DivScale(target->spr.pos.Z - actor->spr.pos.Z, dist, 10); - const VECTORDATA* meleeVector = &gVectorData[22]; - if (weaponType == kGenDudeWeaponThrow) - { - if (abs(losAngle) < kAng15) - { - if (!gThingInfoExtra[curWeapon - kThingBase].allowThrow) - { - if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeChaseW); - else aiGenDudeNewState(actor, &genDudeChaseL); - return; + int curWeapon = actor->genDudeExtra.curWeapon; + int weaponType = actor->genDudeExtra.weaponType; - } - else if (dist < 12264 && dist > 7680 && !spriteIsUnderwater(actor, false) && curWeapon != kModernThingEnemyLifeLeech) - { - int pHit = HitScan(actor, actor->spr.pos.Z, dx, dy, 0, 16777280, 0); - switch (pHit) { - case 0: - case 4: - return; - default: - aiGenDudeNewState(actor, &genDudeThrow); - return; - } + auto actLeech = leechIsDropped(actor); - } - else if (dist > 4072 && dist <= 11072 && !spriteIsUnderwater(actor, false) && !actor->GetSpecialOwner()) - { - switch (curWeapon) - { - case kModernThingEnemyLifeLeech: - { - if (actLeech == nullptr) - { - aiGenDudeNewState(actor, &genDudeThrow2); - genDudeThrow2.nextState = &genDudeDodgeShortL; - return; - } + const VECTORDATA* meleeVector = &gVectorData[22]; + if (weaponType == kGenDudeWeaponThrow) + { + if (abs(losAngle) < kAng15) + { + if (!gThingInfoExtra[curWeapon - kThingBase].allowThrow) + { + if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeChaseW); + else aiGenDudeNewState(actor, &genDudeChaseL); + return; - int ldist = aiFightGetTargetDist(target, pDudeInfo, actLeech); - if (ldist > 3 || !cansee(target->spr.pos.X, target->spr.pos.Y, target->spr.pos.Z, target->spr.sector(), - actLeech->spr.pos.X, actLeech->spr.pos.Y, actLeech->spr.pos.Z, actLeech->spr.sector()) || actLeech->GetTarget() == nullptr) - { - aiGenDudeNewState(actor, &genDudeThrow2); - genDudeThrow2.nextState = &genDudeDodgeShortL; - } - else - { - genDudeThrow2.nextState = &genDudeChaseL; - if (dist > 5072 && Chance(0x5000)) - { - if (!canDuck(actor) || Chance(0x4000)) aiGenDudeNewState(actor, &genDudeDodgeShortL); - else aiGenDudeNewState(actor, &genDudeDodgeShortD); - } - else - { - aiGenDudeNewState(actor, &genDudeChaseL); - } + } + else if (dist < 12264 && dist > 7680 && !spriteIsUnderwater(actor, false) && curWeapon != kModernThingEnemyLifeLeech) + { + int pHit = HitScan(actor, actor->spr.pos.Z, dx, dy, 0, 16777280, 0); + switch (pHit) { + case 0: + case 4: + return; + default: + aiGenDudeNewState(actor, &genDudeThrow); + return; + } - } - } - return; - case kModernThingThrowableRock: - if (Chance(0x4000)) aiGenDudeNewState(actor, &genDudeThrow2); - else playGenDudeSound(actor, kGenDudeSndTargetSpot); - return; - default: - aiGenDudeNewState(actor, &genDudeThrow2); - return; - } + } + else if (dist > 4072 && dist <= 11072 && !spriteIsUnderwater(actor, false) && !actor->GetSpecialOwner()) + { + switch (curWeapon) + { + case kModernThingEnemyLifeLeech: + { + if (actLeech == nullptr) + { + aiGenDudeNewState(actor, &genDudeThrow2); + genDudeThrow2.nextState = &genDudeDodgeShortL; + return; + } - } else if (dist <= meleeVector->maxDist) - { + int ldist = aiFightGetTargetDist(target, pDudeInfo, actLeech); + if (ldist > 3 || !cansee(target->spr.pos.X, target->spr.pos.Y, target->spr.pos.Z, target->spr.sector(), + actLeech->spr.pos.X, actLeech->spr.pos.Y, actLeech->spr.pos.Z, actLeech->spr.sector()) || actLeech->GetTarget() == nullptr) + { + aiGenDudeNewState(actor, &genDudeThrow2); + genDudeThrow2.nextState = &genDudeDodgeShortL; + } + else + { + genDudeThrow2.nextState = &genDudeChaseL; + if (dist > 5072 && Chance(0x5000)) + { + if (!canDuck(actor) || Chance(0x4000)) aiGenDudeNewState(actor, &genDudeDodgeShortL); + else aiGenDudeNewState(actor, &genDudeDodgeShortD); + } + else + { + aiGenDudeNewState(actor, &genDudeChaseL); + } - if (spriteIsUnderwater(actor, false)) - { - if (Chance(0x9000)) aiGenDudeNewState(actor, &genDudePunch); - else aiGenDudeNewState(actor, &genDudeDodgeW); - } - else if (Chance(0x9000)) aiGenDudeNewState(actor, &genDudePunch); - else aiGenDudeNewState(actor, &genDudeDodgeL); - return; + } + } + return; + case kModernThingThrowableRock: + if (Chance(0x4000)) aiGenDudeNewState(actor, &genDudeThrow2); + else playGenDudeSound(actor, kGenDudeSndTargetSpot); + return; + default: + aiGenDudeNewState(actor, &genDudeThrow2); + return; + } - } - else - { - int state = checkAttackState(actor); - if (state == 1) aiGenDudeNewState(actor, &genDudeChaseW); - else if (state == 2) - { - if (Chance(0x5000)) aiGenDudeNewState(actor, &genDudeChaseD); - else aiGenDudeNewState(actor, &genDudeChaseL); - } - else aiGenDudeNewState(actor, &genDudeChaseL); - return; - } - } - } - else - { - int vdist; int mdist; int defDist; - defDist = vdist = mdist = actor->genDudeExtra.fireDist; + } + else if (dist <= meleeVector->maxDist) + { - if (weaponType == kGenDudeWeaponHitscan) - { - if ((vdist = gVectorData[curWeapon].maxDist) <= 0) - vdist = defDist; + if (spriteIsUnderwater(actor, false)) + { + if (Chance(0x9000)) aiGenDudeNewState(actor, &genDudePunch); + else aiGenDudeNewState(actor, &genDudeDodgeW); + } + else if (Chance(0x9000)) aiGenDudeNewState(actor, &genDudePunch); + else aiGenDudeNewState(actor, &genDudeDodgeL); + return; - } - else if (weaponType == kGenDudeWeaponSummon) - { - // don't attack slaves - if (actor->GetTarget() != nullptr && actor->GetTarget()->GetOwner() == actor) - { - aiSetTarget(actor, actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z); - return; - } - else if (actor->genDudeExtra.slaveCount > gGameOptions.nDifficulty || dist < meleeVector->maxDist) - { - if (dist <= meleeVector->maxDist) - { - aiGenDudeNewState(actor, &genDudePunch); - return; - } - else - { - int state = checkAttackState(actor); - if (state == 1) aiGenDudeNewState(actor, &genDudeChaseW); - else if (state == 2) aiGenDudeNewState(actor, &genDudeChaseD); - else aiGenDudeNewState(actor, &genDudeChaseL); - return; - } - } + } + else + { + int state = checkAttackState(actor); + if (state == 1) aiGenDudeNewState(actor, &genDudeChaseW); + else if (state == 2) + { + if (Chance(0x5000)) aiGenDudeNewState(actor, &genDudeChaseD); + else aiGenDudeNewState(actor, &genDudeChaseL); + } + else aiGenDudeNewState(actor, &genDudeChaseL); + return; + } + } + } + else + { + int vdist; int mdist; int defDist; + defDist = vdist = mdist = actor->genDudeExtra.fireDist; - } - else if (weaponType == kGenDudeWeaponMissile) - { - // special handling for flame, explosive and life leech missiles - int state = checkAttackState(actor); - switch (curWeapon) - { - case kMissileLifeLeechRegular: - // pickup life leech if it was thrown previously - if (actLeech != NULL) removeLeech(actLeech); - mdist = 1500; - break; - case kMissileFlareAlt: - mdist = 2500; - [[fallthrough]]; - case kMissileFireball: - case kMissileFireballNapalm: - case kMissileFireballCerberus: - case kMissileFireballTchernobog: - if (mdist == defDist) mdist = 3000; - if (dist > mdist || actor->xspr.locked == 1) break; - else if (dist <= meleeVector->maxDist && Chance(0x9000)) - aiGenDudeNewState(actor, &genDudePunch); - else if (state == 1) aiGenDudeNewState(actor, &genDudeChaseW); - else if (state == 2) aiGenDudeNewState(actor, &genDudeChaseD); - else aiGenDudeNewState(actor, &genDudeChaseL); - return; - case kMissileFlameSpray: - case kMissileFlameHound: - //viewSetSystemMessage("%d", target->xspr.burnTime); - if (spriteIsUnderwater(actor, false)) - { - if (dist > meleeVector->maxDist) aiGenDudeNewState(actor, &genDudeChaseW); - else if (Chance(0x8000)) aiGenDudeNewState(actor, &genDudePunch); - else aiGenDudeNewState(actor, &genDudeDodgeShortW); - return; - } - else if (dist <= 4000 && target->xspr.burnTime >= 2000 && target->GetBurnSource() == actor) - { - if (dist > meleeVector->maxDist) aiGenDudeNewState(actor, &genDudeChaseL); - else aiGenDudeNewState(actor, &genDudePunch); - return; - } - vdist = 3500 + (gGameOptions.nDifficulty * 400); - break; - } - } - else if (weaponType == kGenDudeWeaponKamikaze) - { - int nType = curWeapon - kTrapExploder; - const EXPLOSION* pExpl = &explodeInfo[nType]; - if (CheckProximity(actor, target->spr.pos.X, target->spr.pos.Y, target->spr.pos.Z, target->spr.sector(), pExpl->radius >> 1)) - { - actor->xvel = actor->yvel = actor->zvel = 0; - if (doExplosion(actor, nType) && actor->xspr.health > 0) - actDamageSprite(actor, actor, kDamageExplode, 65535); - } - return; - } + if (weaponType == kGenDudeWeaponHitscan) + { + if ((vdist = gVectorData[curWeapon].maxDist) <= 0) + vdist = defDist; - int state = checkAttackState(actor); - int kAngle = (dudeIsMelee(actor) || dist <= kGenDudeMaxMeleeDist) ? pDudeInfo->periphery : kGenDudeKlabsAng; + } + else if (weaponType == kGenDudeWeaponSummon) + { + // don't attack slaves + if (actor->GetTarget() != nullptr && actor->GetTarget()->GetOwner() == actor) + { + aiSetTarget(actor, actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z); + return; + } + else if (actor->genDudeExtra.slaveCount > gGameOptions.nDifficulty || dist < meleeVector->maxDist) + { + if (dist <= meleeVector->maxDist) + { + aiGenDudeNewState(actor, &genDudePunch); + return; + } + else + { + int state = checkAttackState(actor); + if (state == 1) aiGenDudeNewState(actor, &genDudeChaseW); + else if (state == 2) aiGenDudeNewState(actor, &genDudeChaseD); + else aiGenDudeNewState(actor, &genDudeChaseL); + return; + } + } - if (dist < vdist && abs(losAngle) < kAngle) - { - if (pExtra->canWalk) - { - int objDist = -1; int targetDist = -1; int hit = -1; - if (weaponType == kGenDudeWeaponHitscan) - hit = HitScan(actor, actor->spr.pos.Z, bcos(actor->spr.ang), bsin(actor->spr.ang), actor->dudeSlope, CLIPMASK1, dist); - else if (weaponType == kGenDudeWeaponMissile) - hit = HitScan(actor, actor->spr.pos.Z, bcos(actor->spr.ang), bsin(actor->spr.ang), actor->dudeSlope, CLIPMASK0, dist); - - if (hit >= 0) - { - targetDist = dist - (target->spr.clipdist << 2); - objDist = approxDist(gHitInfo.hitpos.X - actor->spr.pos.X, gHitInfo.hitpos.Y - actor->spr.pos.Y); - } + } + else if (weaponType == kGenDudeWeaponMissile) + { + // special handling for flame, explosive and life leech missiles + int state = checkAttackState(actor); + switch (curWeapon) + { + case kMissileLifeLeechRegular: + // pickup life leech if it was thrown previously + if (actLeech != NULL) removeLeech(actLeech); + mdist = 1500; + break; + case kMissileFlareAlt: + mdist = 2500; + [[fallthrough]]; + case kMissileFireball: + case kMissileFireballNapalm: + case kMissileFireballCerberus: + case kMissileFireballTchernobog: + if (mdist == defDist) mdist = 3000; + if (dist > mdist || actor->xspr.locked == 1) break; + else if (dist <= meleeVector->maxDist && Chance(0x9000)) + aiGenDudeNewState(actor, &genDudePunch); + else if (state == 1) aiGenDudeNewState(actor, &genDudeChaseW); + else if (state == 2) aiGenDudeNewState(actor, &genDudeChaseD); + else aiGenDudeNewState(actor, &genDudeChaseL); + return; + case kMissileFlameSpray: + case kMissileFlameHound: + //viewSetSystemMessage("%d", target->xspr.burnTime); + if (spriteIsUnderwater(actor, false)) + { + if (dist > meleeVector->maxDist) aiGenDudeNewState(actor, &genDudeChaseW); + else if (Chance(0x8000)) aiGenDudeNewState(actor, &genDudePunch); + else aiGenDudeNewState(actor, &genDudeDodgeShortW); + return; + } + else if (dist <= 4000 && target->xspr.burnTime >= 2000 && target->GetBurnSource() == actor) + { + if (dist > meleeVector->maxDist) aiGenDudeNewState(actor, &genDudeChaseL); + else aiGenDudeNewState(actor, &genDudePunch); + return; + } + vdist = 3500 + (gGameOptions.nDifficulty * 400); + break; + } + } + else if (weaponType == kGenDudeWeaponKamikaze) + { + int nType = curWeapon - kTrapExploder; + const EXPLOSION* pExpl = &explodeInfo[nType]; + if (CheckProximity(actor, target->spr.pos.X, target->spr.pos.Y, target->spr.pos.Z, target->spr.sector(), pExpl->radius >> 1)) + { + actor->xvel = actor->yvel = actor->zvel = 0; + if (doExplosion(actor, nType) && actor->xspr.health > 0) + actDamageSprite(actor, actor, kDamageExplode, 65535); + } + return; + } - if (actor != gHitInfo.actor() && targetDist > objDist) - { - DBloodActor* hitactor = nullptr; - walltype* pHWall = NULL; - XWALL* pXHWall = NULL; - bool hscn = false; - bool blck = false; - bool failed = false; + int state = checkAttackState(actor); + int kAngle = (dudeIsMelee(actor) || dist <= kGenDudeMaxMeleeDist) ? pDudeInfo->periphery : kGenDudeKlabsAng; - switch (hit) - { - case 3: - hitactor = gHitInfo.actor(); - if (hitactor) - { - hscn = (hitactor->spr.cstat & CSTAT_SPRITE_BLOCK_HITSCAN); blck = (hitactor->spr.cstat & CSTAT_SPRITE_BLOCK); - } - break; - case 0: - case 4: - pHWall = gHitInfo.hitWall; - if (pHWall->hasX()) pXHWall = &pHWall->xw(); - hscn = (pHWall->cstat & CSTAT_WALL_BLOCK_HITSCAN); blck = (pHWall->cstat & CSTAT_WALL_BLOCK); - break; - } + if (dist < vdist && abs(losAngle) < kAngle) + { + if (pExtra->canWalk) + { + int objDist = -1; int targetDist = -1; int hit = -1; + if (weaponType == kGenDudeWeaponHitscan) + hit = HitScan(actor, actor->spr.pos.Z, bcos(actor->spr.ang), bsin(actor->spr.ang), actor->dudeSlope, CLIPMASK1, dist); + else if (weaponType == kGenDudeWeaponMissile) + hit = HitScan(actor, actor->spr.pos.Z, bcos(actor->spr.ang), bsin(actor->spr.ang), actor->dudeSlope, CLIPMASK0, dist); - switch (hit) { - case 0: - case 1: - case 2: - if (weaponType != kGenDudeWeaponMissile && genDudeAdjustSlope(actor, dist, weaponType) - && dist < (int)(6000 + Random(2000)) && pExtra->baseDispersion < kGenDudeMaxDispersion >> 1) break; + if (hit >= 0) + { + targetDist = dist - (target->spr.clipdist << 2); + objDist = approxDist(gHitInfo.hitpos.X - actor->spr.pos.X, gHitInfo.hitpos.Y - actor->spr.pos.Y); + } - else if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeChaseW); - else aiGenDudeNewState(actor, &genDudeChaseL); - return; - case 3: - if (hitactor->spr.statnum == kStatFX || hitactor->spr.statnum == kStatProjectile || hitactor->spr.statnum == kStatDebris) - break; - if (hitactor->IsDudeActor() && (weaponType != kGenDudeWeaponHitscan || hscn)) - { - // dodge a bit in sides - if (hitactor->GetTarget() != actor) - { - if (pExtra->baseDispersion < 1024 && weaponType != kGenDudeWeaponMissile) - { - if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeDodgeShorterW); - else if (inDuck(actor->xspr.aiState)) aiGenDudeNewState(actor, &genDudeDodgeShorterD); - else aiGenDudeNewState(actor, &genDudeDodgeShorterL); - } - else if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeDodgeShortW); - else if (inDuck(actor->xspr.aiState)) aiGenDudeNewState(actor, &genDudeDodgeShortD); - else aiGenDudeNewState(actor, &genDudeDodgeShortL); + if (actor != gHitInfo.actor() && targetDist > objDist) + { + DBloodActor* hitactor = nullptr; + walltype* pHWall = NULL; + XWALL* pXHWall = NULL; + bool hscn = false; + bool blck = false; + bool failed = false; - switch (hitactor->spr.type) - { - case kDudeModernCustom: // and make dude which could be hit to dodge too - if (!dudeIsMelee(hitactor) && Chance(dist << 4)) - { - if (!inAttack(hitactor->xspr.aiState)) - { - if (spriteIsUnderwater(hitactor)) aiGenDudeNewState(hitactor, &genDudeDodgeShorterW); - else if (inDuck(actor->xspr.aiState)) aiGenDudeNewState(hitactor, &genDudeDodgeShorterD); - else aiGenDudeNewState(hitactor, &genDudeDodgeShorterL); + switch (hit) + { + case 3: + hitactor = gHitInfo.actor(); + if (hitactor) + { + hscn = (hitactor->spr.cstat & CSTAT_SPRITE_BLOCK_HITSCAN); blck = (hitactor->spr.cstat & CSTAT_SPRITE_BLOCK); + } + break; + case 0: + case 4: + pHWall = gHitInfo.hitWall; + if (pHWall->hasX()) pXHWall = &pHWall->xw(); + hscn = (pHWall->cstat & CSTAT_WALL_BLOCK_HITSCAN); blck = (pHWall->cstat & CSTAT_WALL_BLOCK); + break; + } - // preferable in opposite sides - if (Chance(0x8000)) - { - if (actor->xspr.dodgeDir == 1) hitactor->xspr.dodgeDir = -1; - else if (actor->xspr.dodgeDir == -1) hitactor->xspr.dodgeDir = 1; - } - break; - } - if (actor->spr.pos.X < hitactor->spr.pos.X) - { - if (Chance(0x9000) && target->spr.pos.X > hitactor->spr.pos.X) actor->xspr.dodgeDir = -1; - else actor->xspr.dodgeDir = 1; - } - else - { - if (Chance(0x9000) && target->spr.pos.X > hitactor->spr.pos.X) actor->xspr.dodgeDir = 1; - else actor->xspr.dodgeDir = -1; - } - } - break; - default: - if (actor->spr.pos.X < hitactor->spr.pos.X) - { - if (Chance(0x9000) && target->spr.pos.X > hitactor->spr.pos.X) actor->xspr.dodgeDir = -1; - else actor->xspr.dodgeDir = 1; - } - else - { - if (Chance(0x9000) && target->spr.pos.X > hitactor->spr.pos.X) actor->xspr.dodgeDir = 1; - else actor->xspr.dodgeDir = -1; - } - break; - } - return; - } - break; - } - else if (weaponType == kGenDudeWeaponHitscan && hscn) - { - if (genDudeAdjustSlope(actor, dist, weaponType)) break; - VectorScan(actor, 0, 0, bcos(actor->spr.ang), bsin(actor->spr.ang), actor->dudeSlope, dist, 1); - if (actor == gHitInfo.actor()) break; - - bool immune = nnExtIsImmune(hitactor, gVectorData[curWeapon].dmgType); - if (!(hitactor->hasX() && (!immune || (immune && hitactor->spr.statnum == kStatThing && hitactor->xspr.Vector)) && !hitactor->xspr.locked)) - { - if ((approxDist(gHitInfo.hitpos.X - actor->spr.pos.X, gHitInfo.hitpos.Y - actor->spr.pos.Y) <= 1500 && !blck) - || (dist <= (int)(pExtra->fireDist / ClipLow(Random(4), 1)))) - { - //viewSetSystemMessage("GO CHASE"); - if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeChaseW); - else aiGenDudeNewState(actor, &genDudeChaseL); - return; + switch (hit) { + case 0: + case 1: + case 2: + if (weaponType != kGenDudeWeaponMissile && genDudeAdjustSlope(actor, dist, weaponType) + && dist < (int)(6000 + Random(2000)) && pExtra->baseDispersion < kGenDudeMaxDispersion >> 1) break; - } + else if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeChaseW); + else aiGenDudeNewState(actor, &genDudeChaseL); + return; + case 3: + if (hitactor->spr.statnum == kStatFX || hitactor->spr.statnum == kStatProjectile || hitactor->spr.statnum == kStatDebris) + break; + if (hitactor->IsDudeActor() && (weaponType != kGenDudeWeaponHitscan || hscn)) + { + // dodge a bit in sides + if (hitactor->GetTarget() != actor) + { + if (pExtra->baseDispersion < 1024 && weaponType != kGenDudeWeaponMissile) + { + if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeDodgeShorterW); + else if (inDuck(actor->xspr.aiState)) aiGenDudeNewState(actor, &genDudeDodgeShorterD); + else aiGenDudeNewState(actor, &genDudeDodgeShorterL); + } + else if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeDodgeShortW); + else if (inDuck(actor->xspr.aiState)) aiGenDudeNewState(actor, &genDudeDodgeShortD); + else aiGenDudeNewState(actor, &genDudeDodgeShortL); - int wd1 = picWidth(hitactor->spr.picnum, hitactor->spr.xrepeat); - int wd2 = picWidth(actor->spr.picnum, actor->spr.xrepeat); - if (wd1 < (wd2 << 3)) - { - //viewSetSystemMessage("OBJ SIZE: %d DUDE SIZE: %d", wd1, wd2); - if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeDodgeShorterW); - else if (inDuck(actor->xspr.aiState)) aiGenDudeNewState(actor, &genDudeDodgeShorterD); - else aiGenDudeNewState(actor, &genDudeDodgeShorterL); + switch (hitactor->spr.type) + { + case kDudeModernCustom: // and make dude which could be hit to dodge too + if (!dudeIsMelee(hitactor) && Chance(dist << 4)) + { + if (!inAttack(hitactor->xspr.aiState)) + { + if (spriteIsUnderwater(hitactor)) aiGenDudeNewState(hitactor, &genDudeDodgeShorterW); + else if (inDuck(actor->xspr.aiState)) aiGenDudeNewState(hitactor, &genDudeDodgeShorterD); + else aiGenDudeNewState(hitactor, &genDudeDodgeShorterL); - if (actor->spr.pos.X < hitactor->spr.pos.X) - { - if (Chance(0x3000) && target->spr.pos.X > hitactor->spr.pos.X) actor->xspr.dodgeDir = -1; - else actor->xspr.dodgeDir = 1; - } - else - { - if (Chance(0x3000) && target->spr.pos.X > hitactor->spr.pos.X) actor->xspr.dodgeDir = 1; - else actor->xspr.dodgeDir = -1; - } + // preferable in opposite sides + if (Chance(0x8000)) + { + if (actor->xspr.dodgeDir == 1) hitactor->xspr.dodgeDir = -1; + else if (actor->xspr.dodgeDir == -1) hitactor->xspr.dodgeDir = 1; + } + break; + } + if (actor->spr.pos.X < hitactor->spr.pos.X) + { + if (Chance(0x9000) && target->spr.pos.X > hitactor->spr.pos.X) actor->xspr.dodgeDir = -1; + else actor->xspr.dodgeDir = 1; + } + else + { + if (Chance(0x9000) && target->spr.pos.X > hitactor->spr.pos.X) actor->xspr.dodgeDir = 1; + else actor->xspr.dodgeDir = -1; + } + } + break; + default: + if (actor->spr.pos.X < hitactor->spr.pos.X) + { + if (Chance(0x9000) && target->spr.pos.X > hitactor->spr.pos.X) actor->xspr.dodgeDir = -1; + else actor->xspr.dodgeDir = 1; + } + else + { + if (Chance(0x9000) && target->spr.pos.X > hitactor->spr.pos.X) actor->xspr.dodgeDir = 1; + else actor->xspr.dodgeDir = -1; + } + break; + } + return; + } + break; + } + else if (weaponType == kGenDudeWeaponHitscan && hscn) + { + if (genDudeAdjustSlope(actor, dist, weaponType)) break; + VectorScan(actor, 0, 0, bcos(actor->spr.ang), bsin(actor->spr.ang), actor->dudeSlope, dist, 1); + if (actor == gHitInfo.actor()) break; - if (actor->hit.hit.type == kHitWall || actor->hit.hit.type == kHitSprite) - { - if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeChaseW); - else aiGenDudeNewState(actor, &genDudeChaseL); - actor->xspr.goalAng = Random(kAng360); - //viewSetSystemMessage("WALL OR SPRITE TOUCH"); - } + bool immune = nnExtIsImmune(hitactor, gVectorData[curWeapon].dmgType); + if (!(hitactor->hasX() && (!immune || (immune && hitactor->spr.statnum == kStatThing && hitactor->xspr.Vector)) && !hitactor->xspr.locked)) + { + if ((approxDist(gHitInfo.hitpos.X - actor->spr.pos.X, gHitInfo.hitpos.Y - actor->spr.pos.Y) <= 1500 && !blck) + || (dist <= (int)(pExtra->fireDist / ClipLow(Random(4), 1)))) + { + //viewSetSystemMessage("GO CHASE"); + if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeChaseW); + else aiGenDudeNewState(actor, &genDudeChaseL); + return; - } - else - { - if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeChaseW); - else aiGenDudeNewState(actor, &genDudeChaseL); - //viewSetSystemMessage("TOO BIG OBJECT TO DODGE!!!!!!!!"); - } - return; - } - break; - } - [[fallthrough]]; - case 4: - if (hit == 4 && weaponType == kGenDudeWeaponHitscan && hscn) - { - bool masked = (pHWall->cstat & CSTAT_WALL_MASKED); - if (masked) VectorScan(actor, 0, 0, bcos(actor->spr.ang), bsin(actor->spr.ang), actor->dudeSlope, dist, 1); + } - if ((actor != gHitInfo.actor()) && (pHWall->type != kWallGib || !masked || pXHWall == NULL || !pXHWall->triggerVector || pXHWall->locked)) - { - if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeChaseW); - else aiGenDudeNewState(actor, &genDudeChaseL); - return; - } - } - else if (hit >= 3 && weaponType == kGenDudeWeaponMissile && blck) - { - switch (curWeapon) { - case kMissileLifeLeechRegular: - case kMissileTeslaAlt: - case kMissileFlareAlt: - case kMissileFireball: - case kMissileFireballNapalm: - case kMissileFireballCerberus: - case kMissileFireballTchernobog: - { - // allow attack if dude is far from object, but target is close to it - int dudeDist = approxDist(gHitInfo.hitpos.X - actor->spr.pos.X, gHitInfo.hitpos.Y - actor->spr.pos.Y); - int targetDist1 = approxDist(gHitInfo.hitpos.X - target->spr.pos.X, gHitInfo.hitpos.Y - target->spr.pos.Y); - if (dudeDist < mdist) - { - //viewSetSystemMessage("DUDE CLOSE TO OBJ: %d, MDIST: %d", dudeDist, mdist); - if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeChaseW); - else aiGenDudeNewState(actor, &genDudeChaseL); - return; - } - else if (targetDist1 <= mdist >> 1) - { - //viewSetSystemMessage("TARGET CLOSE TO OBJ: %d, MDIST: %d", targetDist, mdist >> 1); - break; - } - [[fallthrough]]; - } - default: - //viewSetSystemMessage("DEF HIT: %d, MDIST: %d", hit, mdist); - if (hit == 4) failed = (pHWall->type != kWallGib || pXHWall == NULL || !pXHWall->triggerVector || pXHWall->locked); - else if (hit == 3 && (failed = (hitactor->spr.statnum != kStatThing || !hitactor->hasX() || hitactor->xspr.locked)) == false) - { - // check also for damage resistance (all possible damages missile can use) - for (int i = 0; i < kDmgMax; i++) - { - if (gMissileInfoExtra[curWeapon - kMissileBase].dmgType[i] && (failed = nnExtIsImmune(hitactor, i)) == false) - break; - } - } + int wd1 = picWidth(hitactor->spr.picnum, hitactor->spr.xrepeat); + int wd2 = picWidth(actor->spr.picnum, actor->spr.xrepeat); + if (wd1 < (wd2 << 3)) + { + //viewSetSystemMessage("OBJ SIZE: %d DUDE SIZE: %d", wd1, wd2); + if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeDodgeShorterW); + else if (inDuck(actor->xspr.aiState)) aiGenDudeNewState(actor, &genDudeDodgeShorterD); + else aiGenDudeNewState(actor, &genDudeDodgeShorterL); - if (failed) - { - if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeSearchW); - else aiGenDudeNewState(actor, &genDudeSearchL); - return; - } - break; - } - } - break; - } - } - } - - aiSetTarget(actor, actor->GetTarget()); - switch (state) - { - case 1: - aiGenDudeNewState(actor, &genDudeFireW); - actor->xspr.aiState->nextState = &genDudeFireW; - break; - case 2: - aiGenDudeNewState(actor, &genDudeFireD); - actor->xspr.aiState->nextState = &genDudeFireD; - break; - default: - aiGenDudeNewState(actor, &genDudeFireL); - actor->xspr.aiState->nextState = &genDudeFireL; - break; - } - } - else - { - if (seqGetID(actor) == actor->xspr.data2 + ((state < 3) ? 8 : 6)) - { - if (state == 1) actor->xspr.aiState->nextState = &genDudeChaseW; - else if (state == 2) actor->xspr.aiState->nextState = &genDudeChaseD; - else actor->xspr.aiState->nextState = &genDudeChaseL; + if (actor->spr.pos.X < hitactor->spr.pos.X) + { + if (Chance(0x3000) && target->spr.pos.X > hitactor->spr.pos.X) actor->xspr.dodgeDir = -1; + else actor->xspr.dodgeDir = 1; + } + else + { + if (Chance(0x3000) && target->spr.pos.X > hitactor->spr.pos.X) actor->xspr.dodgeDir = 1; + else actor->xspr.dodgeDir = -1; + } - } - else if (state == 1 && actor->xspr.aiState != &genDudeChaseW && actor->xspr.aiState != &genDudeFireW) - { - aiGenDudeNewState(actor, &genDudeChaseW); - actor->xspr.aiState->nextState = &genDudeFireW; + if (actor->hit.hit.type == kHitWall || actor->hit.hit.type == kHitSprite) + { + if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeChaseW); + else aiGenDudeNewState(actor, &genDudeChaseL); + actor->xspr.goalAng = Random(kAng360); + //viewSetSystemMessage("WALL OR SPRITE TOUCH"); + } - } - else if (state == 2 && actor->xspr.aiState != &genDudeChaseD && actor->xspr.aiState != &genDudeFireD) - { - aiGenDudeNewState(actor, &genDudeChaseD); - actor->xspr.aiState->nextState = &genDudeFireD; + } + else + { + if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeChaseW); + else aiGenDudeNewState(actor, &genDudeChaseL); + //viewSetSystemMessage("TOO BIG OBJECT TO DODGE!!!!!!!!"); + } + return; + } + break; + } + [[fallthrough]]; + case 4: + if (hit == 4 && weaponType == kGenDudeWeaponHitscan && hscn) + { + bool masked = (pHWall->cstat & CSTAT_WALL_MASKED); + if (masked) VectorScan(actor, 0, 0, bcos(actor->spr.ang), bsin(actor->spr.ang), actor->dudeSlope, dist, 1); - } - else if (actor->xspr.aiState != &genDudeChaseL && actor->xspr.aiState != &genDudeFireL) - { - aiGenDudeNewState(actor, &genDudeChaseL); - actor->xspr.aiState->nextState = &genDudeFireL; - } - } - } - } + if ((actor != gHitInfo.actor()) && (pHWall->type != kWallGib || !masked || pXHWall == NULL || !pXHWall->triggerVector || pXHWall->locked)) + { + if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeChaseW); + else aiGenDudeNewState(actor, &genDudeChaseL); + return; + } + } + else if (hit >= 3 && weaponType == kGenDudeWeaponMissile && blck) + { + switch (curWeapon) { + case kMissileLifeLeechRegular: + case kMissileTeslaAlt: + case kMissileFlareAlt: + case kMissileFireball: + case kMissileFireballNapalm: + case kMissileFireballCerberus: + case kMissileFireballTchernobog: + { + // allow attack if dude is far from object, but target is close to it + int dudeDist = approxDist(gHitInfo.hitpos.X - actor->spr.pos.X, gHitInfo.hitpos.Y - actor->spr.pos.Y); + int targetDist1 = approxDist(gHitInfo.hitpos.X - target->spr.pos.X, gHitInfo.hitpos.Y - target->spr.pos.Y); + if (dudeDist < mdist) + { + //viewSetSystemMessage("DUDE CLOSE TO OBJ: %d, MDIST: %d", dudeDist, mdist); + if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeChaseW); + else aiGenDudeNewState(actor, &genDudeChaseL); + return; + } + else if (targetDist1 <= mdist >> 1) + { + //viewSetSystemMessage("TARGET CLOSE TO OBJ: %d, MDIST: %d", targetDist, mdist >> 1); + break; + } + [[fallthrough]]; + } + default: + //viewSetSystemMessage("DEF HIT: %d, MDIST: %d", hit, mdist); + if (hit == 4) failed = (pHWall->type != kWallGib || pXHWall == NULL || !pXHWall->triggerVector || pXHWall->locked); + else if (hit == 3 && (failed = (hitactor->spr.statnum != kStatThing || !hitactor->hasX() || hitactor->xspr.locked)) == false) + { + // check also for damage resistance (all possible damages missile can use) + for (int i = 0; i < kDmgMax; i++) + { + if (gMissileInfoExtra[curWeapon - kMissileBase].dmgType[i] && (failed = nnExtIsImmune(hitactor, i)) == false) + break; + } + } + + if (failed) + { + if (spriteIsUnderwater(actor)) aiGenDudeNewState(actor, &genDudeSearchW); + else aiGenDudeNewState(actor, &genDudeSearchL); + return; + } + break; + } + } + break; + } + } + } + + aiSetTarget(actor, actor->GetTarget()); + switch (state) + { + case 1: + aiGenDudeNewState(actor, &genDudeFireW); + actor->xspr.aiState->nextState = &genDudeFireW; + break; + case 2: + aiGenDudeNewState(actor, &genDudeFireD); + actor->xspr.aiState->nextState = &genDudeFireD; + break; + default: + aiGenDudeNewState(actor, &genDudeFireL); + actor->xspr.aiState->nextState = &genDudeFireL; + break; + } + } + else + { + if (seqGetID(actor) == actor->xspr.data2 + ((state < 3) ? 8 : 6)) + { + if (state == 1) actor->xspr.aiState->nextState = &genDudeChaseW; + else if (state == 2) actor->xspr.aiState->nextState = &genDudeChaseD; + else actor->xspr.aiState->nextState = &genDudeChaseL; + + } + else if (state == 1 && actor->xspr.aiState != &genDudeChaseW && actor->xspr.aiState != &genDudeFireW) + { + aiGenDudeNewState(actor, &genDudeChaseW); + actor->xspr.aiState->nextState = &genDudeFireW; + + } + else if (state == 2 && actor->xspr.aiState != &genDudeChaseD && actor->xspr.aiState != &genDudeFireD) + { + aiGenDudeNewState(actor, &genDudeChaseD); + actor->xspr.aiState->nextState = &genDudeFireD; + + } + else if (actor->xspr.aiState != &genDudeChaseL && actor->xspr.aiState != &genDudeFireL) + { + aiGenDudeNewState(actor, &genDudeChaseL); + actor->xspr.aiState->nextState = &genDudeFireL; + } + } + } + } } //--------------------------------------------------------------------------- @@ -1038,25 +1039,25 @@ static void unicultThinkChase(DBloodActor* actor) int checkAttackState(DBloodActor* actor) { - if (dudeIsPlayingSeq(actor, 14) || spriteIsUnderwater(actor,false)) - { - if ( !dudeIsPlayingSeq(actor, 14) || spriteIsUnderwater(actor,false)) - { - if (spriteIsUnderwater(actor,false)) - { - return 1; //water - } - } - else - { - return 2; //duck - } - } - else - { - return 3; //land - } - return 0; + if (dudeIsPlayingSeq(actor, 14) || spriteIsUnderwater(actor, false)) + { + if (!dudeIsPlayingSeq(actor, 14) || spriteIsUnderwater(actor, false)) + { + if (spriteIsUnderwater(actor, false)) + { + return 1; //water + } + } + else + { + return 2; //duck + } + } + else + { + return 3; //land + } + return 0; } //--------------------------------------------------------------------------- @@ -1065,40 +1066,40 @@ int checkAttackState(DBloodActor* actor) // //--------------------------------------------------------------------------- -static int getGenDudeMoveSpeed(DBloodActor *actor,int which, bool mul, bool shift) +static int getGenDudeMoveSpeed(DBloodActor* actor, int which, bool mul, bool shift) { - DUDEINFO* pDudeInfo = getDudeInfo(actor->spr.type); - int speed = -1; int step = 2500; int maxSpeed = 146603; - switch(which) - { - case 0: - speed = pDudeInfo->frontSpeed; - break; - case 1: - speed = pDudeInfo->sideSpeed; - break; - case 2: - speed = pDudeInfo->backSpeed; - break; - case 3: - speed = pDudeInfo->angSpeed; - break; - default: - return -1; - } - if (actor->xspr.busyTime > 0) speed /=3; - if (speed > 0 && mul) - { - if (actor->xspr.busyTime > 0) - speed += (step * actor->xspr.busyTime); - } - - if (shift) speed *= 4 >> 4; - if (speed > maxSpeed) speed = maxSpeed; - - return speed; + DUDEINFO* pDudeInfo = getDudeInfo(actor->spr.type); + int speed = -1; int step = 2500; int maxSpeed = 146603; + switch (which) + { + case 0: + speed = pDudeInfo->frontSpeed; + break; + case 1: + speed = pDudeInfo->sideSpeed; + break; + case 2: + speed = pDudeInfo->backSpeed; + break; + case 3: + speed = pDudeInfo->angSpeed; + break; + default: + return -1; + } + if (actor->xspr.busyTime > 0) speed /= 3; + if (speed > 0 && mul) + { + if (actor->xspr.busyTime > 0) + speed += (step * actor->xspr.busyTime); + } + + if (shift) speed *= 4 >> 4; + if (speed > maxSpeed) speed = maxSpeed; + + return speed; } - + //--------------------------------------------------------------------------- // // @@ -1107,54 +1108,54 @@ static int getGenDudeMoveSpeed(DBloodActor *actor,int which, bool mul, bool shif void aiGenDudeMoveForward(DBloodActor* actor) { - DUDEINFO* pDudeInfo = getDudeInfo(actor->spr.type); - GENDUDEEXTRA* pExtra = &actor->genDudeExtra; - int maxTurn = pDudeInfo->angSpeed * 4 >> 4; + DUDEINFO* pDudeInfo = getDudeInfo(actor->spr.type); + GENDUDEEXTRA* pExtra = &actor->genDudeExtra; + int maxTurn = pDudeInfo->angSpeed * 4 >> 4; - if (pExtra->canFly) - { - int nAng = ((actor->xspr.goalAng + 1024 - actor->spr.ang) & 2047) - 1024; - int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4; - actor->spr.ang = (actor->spr.ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047; - int nAccel = pDudeInfo->frontSpeed << 2; - if (abs(nAng) > 341) - return; - if (actor->GetTarget() == nullptr) - actor->spr.ang = (actor->spr.ang + 256) & 2047; - int dx = actor->xspr.targetX - actor->spr.pos.X; - int dy = actor->xspr.targetY - actor->spr.pos.Y; - int nDist = approxDist(dx, dy); - if ((unsigned int)Random(64) < 32 && nDist <= 0x400) - return; - int nCos = Cos(actor->spr.ang); - int nSin = Sin(actor->spr.ang); - int vx = actor->xvel; - int vy = actor->yvel; - int t1 = DMulScale(vx, nCos, vy, nSin, 30); - int t2 = DMulScale(vx, nSin, -vy, nCos, 30); - if (actor->GetTarget() == nullptr) - t1 += nAccel; - else - t1 += nAccel >> 1; - actor->xvel = DMulScale(t1, nCos, t2, nSin, 30); - actor->yvel = DMulScale(t1, nSin, -t2, nCos, 30); - } - else - { - int dang = ((kAng180 + actor->xspr.goalAng - actor->spr.ang) & 2047) - kAng180; - actor->spr.ang = ((actor->spr.ang + ClipRange(dang, -maxTurn, maxTurn)) & 2047); + if (pExtra->canFly) + { + int nAng = ((actor->xspr.goalAng + 1024 - actor->spr.ang) & 2047) - 1024; + int nTurnRange = (pDudeInfo->angSpeed << 2) >> 4; + actor->spr.ang = (actor->spr.ang + ClipRange(nAng, -nTurnRange, nTurnRange)) & 2047; + int nAccel = pDudeInfo->frontSpeed << 2; + if (abs(nAng) > 341) + return; + if (actor->GetTarget() == nullptr) + actor->spr.ang = (actor->spr.ang + 256) & 2047; + int dx = actor->xspr.targetX - actor->spr.pos.X; + int dy = actor->xspr.targetY - actor->spr.pos.Y; + int nDist = approxDist(dx, dy); + if ((unsigned int)Random(64) < 32 && nDist <= 0x400) + return; + int nCos = Cos(actor->spr.ang); + int nSin = Sin(actor->spr.ang); + int vx = actor->xvel; + int vy = actor->yvel; + int t1 = DMulScale(vx, nCos, vy, nSin, 30); + int t2 = DMulScale(vx, nSin, -vy, nCos, 30); + if (actor->GetTarget() == nullptr) + t1 += nAccel; + else + t1 += nAccel >> 1; + actor->xvel = DMulScale(t1, nCos, t2, nSin, 30); + actor->yvel = DMulScale(t1, nSin, -t2, nCos, 30); + } + else + { + int dang = ((kAng180 + actor->xspr.goalAng - actor->spr.ang) & 2047) - kAng180; + actor->spr.ang = ((actor->spr.ang + ClipRange(dang, -maxTurn, maxTurn)) & 2047); - // don't move forward if trying to turn around - if (abs(dang) > kAng60) - return; + // don't move forward if trying to turn around + if (abs(dang) > kAng60) + return; - int sin = Sin(actor->spr.ang); - int cos = Cos(actor->spr.ang); + int sin = Sin(actor->spr.ang); + int cos = Cos(actor->spr.ang); - int frontSpeed = actor->genDudeExtra.moveSpeed; - actor->xvel += MulScale(cos, frontSpeed, 30); - actor->yvel += MulScale(sin, frontSpeed, 30); - } + int frontSpeed = actor->genDudeExtra.moveSpeed; + actor->xvel += MulScale(cos, frontSpeed, 30); + actor->yvel += MulScale(sin, frontSpeed, 30); + } } //--------------------------------------------------------------------------- @@ -1163,43 +1164,43 @@ void aiGenDudeMoveForward(DBloodActor* actor) // //--------------------------------------------------------------------------- -void aiGenDudeChooseDirection(DBloodActor* actor, int a3, int xvel, int yvel) +void aiGenDudeChooseDirection(DBloodActor* actor, int a3, int xvel, int yvel) { - if (!(actor->spr.type >= kDudeBase && actor->spr.type < kDudeMax)) - { - Printf(PRINT_HIGH, "actor->spr.type >= kDudeBase && actor->spr.type < kDudeMax"); - return; - } + if (!(actor->spr.type >= kDudeBase && actor->spr.type < kDudeMax)) + { + Printf(PRINT_HIGH, "actor->spr.type >= kDudeBase && actor->spr.type < kDudeMax"); + return; + } - // TO-DO: Take in account if sprite is flip-x, so enemy select correct angle + // TO-DO: Take in account if sprite is flip-x, so enemy select correct angle - int vc = ((a3 + 1024 - actor->spr.ang) & 2047) - 1024; - int t1 = DMulScale(xvel, Cos(actor->spr.ang), yvel, Sin(actor->spr.ang), 30); - int vsi = ((t1 * 15) >> 12) / 2; int v8 = (vc >= 0) ? 341 : -341; - - if (CanMove(actor, actor->GetTarget(), actor->spr.ang + vc, vsi)) - actor->xspr.goalAng = actor->spr.ang + vc; - else if (CanMove(actor, actor->GetTarget(), actor->spr.ang + vc / 2, vsi)) - actor->xspr.goalAng = actor->spr.ang + vc / 2; - else if (CanMove(actor, actor->GetTarget(), actor->spr.ang - vc / 2, vsi)) - actor->xspr.goalAng = actor->spr.ang - vc / 2; - else if (CanMove(actor, actor->GetTarget(), actor->spr.ang + v8, vsi)) - actor->xspr.goalAng = actor->spr.ang + v8; - else if (CanMove(actor, actor->GetTarget(), actor->spr.ang, vsi)) - actor->xspr.goalAng = actor->spr.ang; - else if (CanMove(actor, actor->GetTarget(), actor->spr.ang - v8, vsi)) - actor->xspr.goalAng = actor->spr.ang - v8; - else - actor->xspr.goalAng = actor->spr.ang + 341; - - actor->xspr.dodgeDir = (Chance(0x8000)) ? 1 : -1; + int vc = ((a3 + 1024 - actor->spr.ang) & 2047) - 1024; + int t1 = DMulScale(xvel, Cos(actor->spr.ang), yvel, Sin(actor->spr.ang), 30); + int vsi = ((t1 * 15) >> 12) / 2; int v8 = (vc >= 0) ? 341 : -341; - if (!CanMove(actor, actor->GetTarget(), actor->spr.ang + actor->xspr.dodgeDir * 512, 512)) - { - actor->xspr.dodgeDir = -actor->xspr.dodgeDir; - if (!CanMove(actor, actor->GetTarget(), actor->spr.ang + actor->xspr.dodgeDir * 512, 512)) - actor->xspr.dodgeDir = 0; - } + if (CanMove(actor, actor->GetTarget(), actor->spr.ang + vc, vsi)) + actor->xspr.goalAng = actor->spr.ang + vc; + else if (CanMove(actor, actor->GetTarget(), actor->spr.ang + vc / 2, vsi)) + actor->xspr.goalAng = actor->spr.ang + vc / 2; + else if (CanMove(actor, actor->GetTarget(), actor->spr.ang - vc / 2, vsi)) + actor->xspr.goalAng = actor->spr.ang - vc / 2; + else if (CanMove(actor, actor->GetTarget(), actor->spr.ang + v8, vsi)) + actor->xspr.goalAng = actor->spr.ang + v8; + else if (CanMove(actor, actor->GetTarget(), actor->spr.ang, vsi)) + actor->xspr.goalAng = actor->spr.ang; + else if (CanMove(actor, actor->GetTarget(), actor->spr.ang - v8, vsi)) + actor->xspr.goalAng = actor->spr.ang - v8; + else + actor->xspr.goalAng = actor->spr.ang + 341; + + actor->xspr.dodgeDir = (Chance(0x8000)) ? 1 : -1; + + if (!CanMove(actor, actor->GetTarget(), actor->spr.ang + actor->xspr.dodgeDir * 512, 512)) + { + actor->xspr.dodgeDir = -actor->xspr.dodgeDir; + if (!CanMove(actor, actor->GetTarget(), actor->spr.ang + actor->xspr.dodgeDir * 512, 512)) + actor->xspr.dodgeDir = 0; + } } //--------------------------------------------------------------------------- @@ -1208,62 +1209,62 @@ void aiGenDudeChooseDirection(DBloodActor* actor, int a3, int xvel, int yvel) // //--------------------------------------------------------------------------- -void aiGenDudeNewState(DBloodActor* actor, AISTATE* pAIState) +void aiGenDudeNewState(DBloodActor* actor, AISTATE* pAIState) { - if (!actor->hasX()) - { - return; - } + if (!actor->hasX()) + { + return; + } - // redirect dudes which cannot walk to non-walk states - if (!actor->genDudeExtra.canWalk) - { - - if (pAIState == &genDudeDodgeL || pAIState == &genDudeDodgeShortL || pAIState == &genDudeDodgeShorterL) - pAIState = &genDudeRecoilL; + // redirect dudes which cannot walk to non-walk states + if (!actor->genDudeExtra.canWalk) + { - else if (pAIState == &genDudeDodgeD || pAIState == &genDudeDodgeShortD || pAIState == &genDudeDodgeShorterD) - pAIState = &genDudeRecoilD; + if (pAIState == &genDudeDodgeL || pAIState == &genDudeDodgeShortL || pAIState == &genDudeDodgeShorterL) + pAIState = &genDudeRecoilL; - else if (pAIState == &genDudeDodgeW || pAIState == &genDudeDodgeShortW || pAIState == &genDudeDodgeShorterW) - pAIState = &genDudeRecoilW; + else if (pAIState == &genDudeDodgeD || pAIState == &genDudeDodgeShortD || pAIState == &genDudeDodgeShorterD) + pAIState = &genDudeRecoilD; - else if (pAIState == &genDudeSearchL || pAIState == &genDudeSearchShortL) - pAIState = &genDudeSearchNoWalkL; + else if (pAIState == &genDudeDodgeW || pAIState == &genDudeDodgeShortW || pAIState == &genDudeDodgeShorterW) + pAIState = &genDudeRecoilW; - else if (pAIState == &genDudeSearchW || pAIState == &genDudeSearchShortW) - pAIState = &genDudeSearchNoWalkW; + else if (pAIState == &genDudeSearchL || pAIState == &genDudeSearchShortL) + pAIState = &genDudeSearchNoWalkL; - else if (pAIState == &genDudeGotoL) pAIState = &genDudeIdleL; - else if (pAIState == &genDudeGotoW) pAIState = &genDudeIdleW; - else if (pAIState == &genDudeChaseL) pAIState = &genDudeChaseNoWalkL; - else if (pAIState == &genDudeChaseD) pAIState = &genDudeChaseNoWalkD; - else if (pAIState == &genDudeChaseW) pAIState = &genDudeChaseNoWalkW; - else if (pAIState == &genDudeRecoilTesla) { - - if (spriteIsUnderwater(actor, false)) pAIState = &genDudeRecoilW; - else pAIState = &genDudeRecoilL; + else if (pAIState == &genDudeSearchW || pAIState == &genDudeSearchShortW) + pAIState = &genDudeSearchNoWalkW; - } + else if (pAIState == &genDudeGotoL) pAIState = &genDudeIdleL; + else if (pAIState == &genDudeGotoW) pAIState = &genDudeIdleW; + else if (pAIState == &genDudeChaseL) pAIState = &genDudeChaseNoWalkL; + else if (pAIState == &genDudeChaseD) pAIState = &genDudeChaseNoWalkD; + else if (pAIState == &genDudeChaseW) pAIState = &genDudeChaseNoWalkW; + else if (pAIState == &genDudeRecoilTesla) { - } + if (spriteIsUnderwater(actor, false)) pAIState = &genDudeRecoilW; + else pAIState = &genDudeRecoilL; - if (!actor->genDudeExtra.canRecoil) - { - if (pAIState == &genDudeRecoilL || pAIState == &genDudeRecoilD) pAIState = &genDudeIdleL; - else if (pAIState == &genDudeRecoilW) pAIState = &genDudeIdleW; - } - - actor->xspr.stateTimer = pAIState->stateTicks; actor->xspr.aiState = pAIState; - - int stateSeq = actor->xspr.data2 + pAIState->seqId; - if (pAIState->seqId >= 0 && getSequence(stateSeq)) - { - seqSpawn(stateSeq, actor, pAIState->funcId); - } + } - if (pAIState->enterFunc) - pAIState->enterFunc(actor); + } + + if (!actor->genDudeExtra.canRecoil) + { + if (pAIState == &genDudeRecoilL || pAIState == &genDudeRecoilD) pAIState = &genDudeIdleL; + else if (pAIState == &genDudeRecoilW) pAIState = &genDudeIdleW; + } + + actor->xspr.stateTimer = pAIState->stateTicks; actor->xspr.aiState = pAIState; + + int stateSeq = actor->xspr.data2 + pAIState->seqId; + if (pAIState->seqId >= 0 && getSequence(stateSeq)) + { + seqSpawn(stateSeq, actor, pAIState->funcId); + } + + if (pAIState->enterFunc) + pAIState->enterFunc(actor); } //--------------------------------------------------------------------------- @@ -1272,90 +1273,90 @@ void aiGenDudeNewState(DBloodActor* actor, AISTATE* pAIState) // //--------------------------------------------------------------------------- -bool playGenDudeSound(DBloodActor* actor, int mode) +bool playGenDudeSound(DBloodActor* actor, int mode) { - if (mode < kGenDudeSndTargetSpot || mode >= kGenDudeSndMax) return false; - const GENDUDESND* sndInfo = &gCustomDudeSnd[mode]; bool gotSnd = false; - int sndStartId = actor->xspr.sysData1; - int rand = sndInfo->randomRange; - int sndId = (sndStartId <= 0) ? sndInfo->defaultSndId : sndStartId + sndInfo->sndIdOffset; - GENDUDEEXTRA* pExtra = &actor->genDudeExtra; + if (mode < kGenDudeSndTargetSpot || mode >= kGenDudeSndMax) return false; + const GENDUDESND* sndInfo = &gCustomDudeSnd[mode]; bool gotSnd = false; + int sndStartId = actor->xspr.sysData1; + int rand = sndInfo->randomRange; + int sndId = (sndStartId <= 0) ? sndInfo->defaultSndId : sndStartId + sndInfo->sndIdOffset; + GENDUDEEXTRA* pExtra = &actor->genDudeExtra; - // let's check if there same sounds already played by other dudes - // so we won't get a lot of annoying screams in the same time and ensure sound played in it's full length (if not interruptable) - if (pExtra->sndPlaying && !sndInfo->interruptable) { + // let's check if there same sounds already played by other dudes + // so we won't get a lot of annoying screams in the same time and ensure sound played in it's full length (if not interruptable) + if (pExtra->sndPlaying && !sndInfo->interruptable) { #if 0 - for (int i = 0; i < 256; i++) { - if (Bonkle[i].atc <= 0) continue; - for (int a = 0; a < rand; a++) { - if (sndId + a == Bonkle[i].atc) { - if (Bonkle[i].at0 <= 0) { - pExtra->sndPlaying = false; - break; - } - return true; - } - } - } + for (int i = 0; i < 256; i++) { + if (Bonkle[i].atc <= 0) continue; + for (int a = 0; a < rand; a++) { + if (sndId + a == Bonkle[i].atc) { + if (Bonkle[i].at0 <= 0) { + pExtra->sndPlaying = false; + break; + } + return true; + } + } + } #endif - pExtra->sndPlaying = false; - - } + pExtra->sndPlaying = false; - if (sndId < 0) return false; - else if (sndStartId <= 0) { sndId += Random(rand); gotSnd = true; } - else - { - // Let's try to get random snd - int maxRetries = 5; - while (maxRetries-- > 0) { - int random = Random(rand); - if (!soundEngine->FindSoundByResID(sndId + random)) continue; - sndId = sndId + random; - gotSnd = true; - break; - } + } - // If no success in getting random snd, get first existing one - if (gotSnd == false) - { - int maxSndId = sndId + rand; - while (sndId++ < maxSndId) - { - if (!soundEngine->FindSoundByResID(sndId)) continue; - gotSnd = true; - break; - } - } + if (sndId < 0) return false; + else if (sndStartId <= 0) { sndId += Random(rand); gotSnd = true; } + else + { + // Let's try to get random snd + int maxRetries = 5; + while (maxRetries-- > 0) { + int random = Random(rand); + if (!soundEngine->FindSoundByResID(sndId + random)) continue; + sndId = sndId + random; + gotSnd = true; + break; + } - } + // If no success in getting random snd, get first existing one + if (gotSnd == false) + { + int maxSndId = sndId + rand; + while (sndId++ < maxSndId) + { + if (!soundEngine->FindSoundByResID(sndId)) continue; + gotSnd = true; + break; + } + } - if (gotSnd == false) return false; - else if (sndInfo->aiPlaySound) aiPlay3DSound(actor, sndId, AI_SFX_PRIORITY_2, -1); - else sfxPlay3DSound(actor, sndId, -1, 0); - - pExtra->sndPlaying = true; - return true; + } + + if (gotSnd == false) return false; + else if (sndInfo->aiPlaySound) aiPlay3DSound(actor, sndId, AI_SFX_PRIORITY_2, -1); + else sfxPlay3DSound(actor, sndId, -1, 0); + + pExtra->sndPlaying = true; + return true; } - + //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- -bool spriteIsUnderwater(DBloodActor* actor, bool oldWay) +bool spriteIsUnderwater(DBloodActor* actor, bool oldWay) { - return (IsUnderwaterSector(actor->spr.sector()) - || (oldWay && (actor->xspr.medium == kMediumWater || actor->xspr.medium == kMediumGoo))); + return (IsUnderwaterSector(actor->spr.sector()) + || (oldWay && (actor->xspr.medium == kMediumWater || actor->xspr.medium == kMediumGoo))); } -DBloodActor* leechIsDropped(DBloodActor* actor) +DBloodActor* leechIsDropped(DBloodActor* actor) { - return actor->genDudeExtra.pLifeLeech; + return actor->genDudeExtra.pLifeLeech; } - + //--------------------------------------------------------------------------- // // @@ -1364,79 +1365,79 @@ DBloodActor* leechIsDropped(DBloodActor* actor) void removeDudeStuff(DBloodActor* actor) { - BloodStatIterator it(kStatThing); - while (auto actor2 = it.Next()) - { - if (actor2->GetOwner() != actor) continue; - switch (actor2->spr.type) { - case kThingArmedProxBomb: - case kThingArmedRemoteBomb: - case kModernThingTNTProx: - actor2->spr.type = kSpriteDecoration; - actPostSprite(actor2, kStatFree); - break; - case kModernThingEnemyLifeLeech: - killDudeLeech(actor2); - break; - } - } + BloodStatIterator it(kStatThing); + while (auto actor2 = it.Next()) + { + if (actor2->GetOwner() != actor) continue; + switch (actor2->spr.type) { + case kThingArmedProxBomb: + case kThingArmedRemoteBomb: + case kModernThingTNTProx: + actor2->spr.type = kSpriteDecoration; + actPostSprite(actor2, kStatFree); + break; + case kModernThingEnemyLifeLeech: + killDudeLeech(actor2); + break; + } + } - it.Reset(kStatDude); - while (auto actor2 = it.Next()) - { - if (actor2->GetOwner() != actor) continue; - actDamageSprite(actor2->GetOwner(), actor2, kDamageFall, 65535); - } + it.Reset(kStatDude); + while (auto actor2 = it.Next()) + { + if (actor2->GetOwner() != actor) continue; + actDamageSprite(actor2->GetOwner(), actor2, kDamageFall, 65535); + } } - + //--------------------------------------------------------------------------- // // // //--------------------------------------------------------------------------- -void removeLeech(DBloodActor* actLeech, bool delSprite) +void removeLeech(DBloodActor* actLeech, bool delSprite) { - if (actLeech != nullptr) - { - auto effectactor = gFX.fxSpawnActor((FX_ID)52, actLeech->spr.sector(), actLeech->spr.pos.X, actLeech->spr.pos.Y, actLeech->spr.pos.Z, actLeech->spr.ang); - if (effectactor != nullptr) - { - effectactor->spr.cstat = CSTAT_SPRITE_ALIGNMENT_FACING; - effectactor->spr.pal = 6; - int repeat = 64 + Random(50); - effectactor->spr.xrepeat = repeat; - effectactor->spr.yrepeat = repeat; - } - - sfxPlay3DSoundCP(actLeech, 490, -1, 0,60000); - - if (actLeech->GetOwner()) - actLeech->GetOwner()->genDudeExtra.pLifeLeech = nullptr; + if (actLeech != nullptr) + { + auto effectactor = gFX.fxSpawnActor((FX_ID)52, actLeech->spr.sector(), actLeech->spr.pos.X, actLeech->spr.pos.Y, actLeech->spr.pos.Z, actLeech->spr.ang); + if (effectactor != nullptr) + { + effectactor->spr.cstat = CSTAT_SPRITE_ALIGNMENT_FACING; + effectactor->spr.pal = 6; + int repeat = 64 + Random(50); + effectactor->spr.xrepeat = repeat; + effectactor->spr.yrepeat = repeat; + } - if (delSprite) - { - actLeech->spr.type = kSpriteDecoration; - actPostSprite(actLeech, kStatFree); - } + sfxPlay3DSoundCP(actLeech, 490, -1, 0, 60000); + + if (actLeech->GetOwner()) + actLeech->GetOwner()->genDudeExtra.pLifeLeech = nullptr; + + if (delSprite) + { + actLeech->spr.type = kSpriteDecoration; + actPostSprite(actLeech, kStatFree); + } - } + } } - -void killDudeLeech(DBloodActor* actLeech) + +void killDudeLeech(DBloodActor* actLeech) { - if (actLeech != NULL) - { - actDamageSprite(actLeech->GetOwner(), actLeech, kDamageExplode, 65535); - sfxPlay3DSoundCP(actLeech, 522, -1, 0, 60000); + if (actLeech != NULL) + { + actDamageSprite(actLeech->GetOwner(), actLeech, kDamageExplode, 65535); + sfxPlay3DSoundCP(actLeech, 522, -1, 0, 60000); - if (actLeech->GetOwner() != nullptr) - actLeech->GetOwner()->genDudeExtra.pLifeLeech = nullptr; - } + if (actLeech->GetOwner() != nullptr) + actLeech->GetOwner()->genDudeExtra.pLifeLeech = nullptr; + } } - + //--------------------------------------------------------------------------- // // @@ -1445,18 +1446,18 @@ void killDudeLeech(DBloodActor* actLeech) DBloodActor* getNextIncarnation(DBloodActor* actor) { - for (int i = bucketHead[actor->xspr.txID]; i < bucketHead[actor->xspr.txID + 1]; i++) - { - if (!rxBucket[i].isActor()) continue; + for (int i = bucketHead[actor->xspr.txID]; i < bucketHead[actor->xspr.txID + 1]; i++) + { + if (!rxBucket[i].isActor()) continue; auto rxactor = rxBucket[i].actor(); - if (actor != rxactor && rxactor->spr.statnum == kStatInactive) return rxactor; - } - return nullptr; + if (actor != rxactor && rxactor->spr.statnum == kStatInactive) return rxactor; + } + return nullptr; } bool dudeIsMelee(DBloodActor* actor) { - return actor->genDudeExtra.isMelee; + return actor->genDudeExtra.isMelee; } //--------------------------------------------------------------------------- @@ -1465,202 +1466,202 @@ bool dudeIsMelee(DBloodActor* actor) // //--------------------------------------------------------------------------- -static void scaleDamage(DBloodActor* actor) +static void scaleDamage(DBloodActor* actor) { - int curWeapon = actor->genDudeExtra.curWeapon; - int weaponType = actor->genDudeExtra.weaponType; - signed short* curScale = actor->genDudeExtra.dmgControl; - for (int i = 0; i < kDmgMax; i++) - curScale[i] = getDudeInfo(kDudeModernCustom)->startDamage[i]; + int curWeapon = actor->genDudeExtra.curWeapon; + int weaponType = actor->genDudeExtra.weaponType; + signed short* curScale = actor->genDudeExtra.dmgControl; + for (int i = 0; i < kDmgMax; i++) + curScale[i] = getDudeInfo(kDudeModernCustom)->startDamage[i]; - switch (weaponType) { - // just copy damage resistance of dude that should be summoned - case kGenDudeWeaponSummon: - for (int i = 0; i < kDmgMax; i++) - curScale[i] = getDudeInfo(curWeapon)->startDamage[i]; - break; - // these does not like the explosions and burning - case kGenDudeWeaponKamikaze: - curScale[kDmgBurn] = curScale[kDmgExplode] = curScale[kDmgElectric] = 1024; - break; - case kGenDudeWeaponMissile: - case kGenDudeWeaponThrow: - switch (curWeapon) - { - case kMissileButcherKnife: - curScale[kDmgBullet] = 100; - [[fallthrough]]; - case kMissileEctoSkull: - curScale[kDmgSpirit] = 32; - break; - case kMissileLifeLeechAltNormal: - case kMissileLifeLeechAltSmall: - case kMissileArcGargoyle: - curScale[kDmgSpirit] -= 32; - curScale[kDmgElectric] = 52; - break; - case kMissileFlareRegular: - case kMissileFlareAlt: - case kMissileFlameSpray: - case kMissileFlameHound: - case kThingArmedSpray: - case kThingPodFireBall: - case kThingNapalmBall: - curScale[kDmgBurn] = 32; - break; - case kMissileLifeLeechRegular: - curScale[kDmgBurn] = 60 + Random(4); - [[fallthrough]]; - case kThingDroppedLifeLeech: - case kModernThingEnemyLifeLeech: - curScale[kDmgSpirit] = 32 + Random(18); - break; - case kMissileFireball: - case kMissileFireballNapalm: - case kMissileFireballCerberus: - case kMissileFireballTchernobog: - curScale[kDmgBurn] = 50; - curScale[kDmgExplode] -= 32; - curScale[kDmgFall] = 65 + Random(15); - break; - case kThingTNTBarrel: - case kThingArmedProxBomb: - case kThingArmedRemoteBomb: - case kThingArmedTNTBundle: - case kThingArmedTNTStick: - case kModernThingTNTProx: - curScale[kDmgBurn] -= 32; - curScale[kDmgExplode] -= 32; - curScale[kDmgFall] = 65 + Random(15); - break; - case kMissileTeslaAlt: - case kMissileTeslaRegular: - curScale[kDmgElectric] = 32 + Random(8); - break; - } - break; + switch (weaponType) { + // just copy damage resistance of dude that should be summoned + case kGenDudeWeaponSummon: + for (int i = 0; i < kDmgMax; i++) + curScale[i] = getDudeInfo(curWeapon)->startDamage[i]; + break; + // these does not like the explosions and burning + case kGenDudeWeaponKamikaze: + curScale[kDmgBurn] = curScale[kDmgExplode] = curScale[kDmgElectric] = 1024; + break; + case kGenDudeWeaponMissile: + case kGenDudeWeaponThrow: + switch (curWeapon) + { + case kMissileButcherKnife: + curScale[kDmgBullet] = 100; + [[fallthrough]]; + case kMissileEctoSkull: + curScale[kDmgSpirit] = 32; + break; + case kMissileLifeLeechAltNormal: + case kMissileLifeLeechAltSmall: + case kMissileArcGargoyle: + curScale[kDmgSpirit] -= 32; + curScale[kDmgElectric] = 52; + break; + case kMissileFlareRegular: + case kMissileFlareAlt: + case kMissileFlameSpray: + case kMissileFlameHound: + case kThingArmedSpray: + case kThingPodFireBall: + case kThingNapalmBall: + curScale[kDmgBurn] = 32; + break; + case kMissileLifeLeechRegular: + curScale[kDmgBurn] = 60 + Random(4); + [[fallthrough]]; + case kThingDroppedLifeLeech: + case kModernThingEnemyLifeLeech: + curScale[kDmgSpirit] = 32 + Random(18); + break; + case kMissileFireball: + case kMissileFireballNapalm: + case kMissileFireballCerberus: + case kMissileFireballTchernobog: + curScale[kDmgBurn] = 50; + curScale[kDmgExplode] -= 32; + curScale[kDmgFall] = 65 + Random(15); + break; + case kThingTNTBarrel: + case kThingArmedProxBomb: + case kThingArmedRemoteBomb: + case kThingArmedTNTBundle: + case kThingArmedTNTStick: + case kModernThingTNTProx: + curScale[kDmgBurn] -= 32; + curScale[kDmgExplode] -= 32; + curScale[kDmgFall] = 65 + Random(15); + break; + case kMissileTeslaAlt: + case kMissileTeslaRegular: + curScale[kDmgElectric] = 32 + Random(8); + break; + } + break; - } + } - // add resistance if have an armor item to drop - if (actor->xspr.dropMsg >= kItemArmorAsbest && actor->xspr.dropMsg <= kItemArmorSuper) - { - switch (actor->xspr.dropMsg) - { - case kItemArmorAsbest: - curScale[kDmgBurn] = 0; - curScale[kDmgExplode] -= 30; - break; - case kItemArmorBasic: - curScale[kDmgBurn] -= 15; - curScale[kDmgExplode] -= 15; - curScale[kDmgBullet] -= 15; - curScale[kDmgSpirit] -= 15; - break; - case kItemArmorBody: - curScale[kDmgBullet] -= 30; - break; - case kItemArmorFire: - curScale[kDmgBurn] -= 30; - curScale[kDmgExplode] -= 30; - break; - case kItemArmorSpirit: - curScale[kDmgSpirit] -= 30; - break; - case kItemArmorSuper: - curScale[kDmgBurn] -= 60; - curScale[kDmgExplode] -= 60; - curScale[kDmgBullet] -= 60; - curScale[kDmgSpirit] -= 60; - break; - } - } + // add resistance if have an armor item to drop + if (actor->xspr.dropMsg >= kItemArmorAsbest && actor->xspr.dropMsg <= kItemArmorSuper) + { + switch (actor->xspr.dropMsg) + { + case kItemArmorAsbest: + curScale[kDmgBurn] = 0; + curScale[kDmgExplode] -= 30; + break; + case kItemArmorBasic: + curScale[kDmgBurn] -= 15; + curScale[kDmgExplode] -= 15; + curScale[kDmgBullet] -= 15; + curScale[kDmgSpirit] -= 15; + break; + case kItemArmorBody: + curScale[kDmgBullet] -= 30; + break; + case kItemArmorFire: + curScale[kDmgBurn] -= 30; + curScale[kDmgExplode] -= 30; + break; + case kItemArmorSpirit: + curScale[kDmgSpirit] -= 30; + break; + case kItemArmorSuper: + curScale[kDmgBurn] -= 60; + curScale[kDmgExplode] -= 60; + curScale[kDmgBullet] -= 60; + curScale[kDmgSpirit] -= 60; + break; + } + } - // take in account yrepeat of sprite - int yrepeat = actor->spr.yrepeat; - if (yrepeat < 64) - { - for (int i = 0; i < kDmgMax; i++) curScale[i] += (64 - yrepeat); - } - else if (yrepeat > 64) - { - for (int i = 0; i < kDmgMax; i++) curScale[i] -= ((yrepeat - 64) >> 2); - } + // take in account yrepeat of sprite + int yrepeat = actor->spr.yrepeat; + if (yrepeat < 64) + { + for (int i = 0; i < kDmgMax; i++) curScale[i] += (64 - yrepeat); + } + else if (yrepeat > 64) + { + for (int i = 0; i < kDmgMax; i++) curScale[i] -= ((yrepeat - 64) >> 2); + } - // take surface type into account - int surfType = tileGetSurfType(actor->spr.picnum); - switch (surfType) - { - case 1: // stone - curScale[kDmgFall] = 0; - curScale[kDmgBullet] -= 200; - curScale[kDmgBurn] -= 100; - curScale[kDmgExplode] -= 80; - curScale[kDmgChoke] += 30; - curScale[kDmgElectric] += 20; - break; - case 2: // metal - curScale[kDmgFall] = 16; - curScale[kDmgBullet] -= 128; - curScale[kDmgBurn] -= 90; - curScale[kDmgExplode] -= 55; - curScale[kDmgChoke] += 20; - curScale[kDmgElectric] += 30; - break; - case 3: // wood - curScale[kDmgBullet] -= 10; - curScale[kDmgBurn] += 50; - curScale[kDmgExplode] += 40; - curScale[kDmgChoke] += 10; - curScale[kDmgElectric] -= 60; - break; - case 5: // water - case 6: // dirt - case 7: // clay - case 13: // goo - curScale[kDmgFall] = 8; - curScale[kDmgBullet] -= 20; - curScale[kDmgBurn] -= 200; - curScale[kDmgExplode] -= 60; - curScale[kDmgChoke] = 0; - curScale[kDmgElectric] += 40; - break; - case 8: // snow - case 9: // ice - curScale[kDmgFall] = 8; - curScale[kDmgBullet] -= 20; - curScale[kDmgBurn] -= 100; - curScale[kDmgExplode] -= 50; - curScale[kDmgChoke] = 0; - curScale[kDmgElectric] += 40; - break; - case 10: // leaves - case 12: // plant - curScale[kDmgFall] = 0; - curScale[kDmgBullet] -= 10; - curScale[kDmgBurn] += 70; - curScale[kDmgExplode] += 50; - break; - case 11: // cloth - curScale[kDmgFall] = 8; - curScale[kDmgBullet] -= 10; - curScale[kDmgBurn] += 30; - curScale[kDmgExplode] += 20; - break; - case 14: // lava - curScale[kDmgBurn] = 0; - curScale[kDmgExplode] = 0; - curScale[kDmgChoke] += 30; - break; - } + // take surface type into account + int surfType = tileGetSurfType(actor->spr.picnum); + switch (surfType) + { + case 1: // stone + curScale[kDmgFall] = 0; + curScale[kDmgBullet] -= 200; + curScale[kDmgBurn] -= 100; + curScale[kDmgExplode] -= 80; + curScale[kDmgChoke] += 30; + curScale[kDmgElectric] += 20; + break; + case 2: // metal + curScale[kDmgFall] = 16; + curScale[kDmgBullet] -= 128; + curScale[kDmgBurn] -= 90; + curScale[kDmgExplode] -= 55; + curScale[kDmgChoke] += 20; + curScale[kDmgElectric] += 30; + break; + case 3: // wood + curScale[kDmgBullet] -= 10; + curScale[kDmgBurn] += 50; + curScale[kDmgExplode] += 40; + curScale[kDmgChoke] += 10; + curScale[kDmgElectric] -= 60; + break; + case 5: // water + case 6: // dirt + case 7: // clay + case 13: // goo + curScale[kDmgFall] = 8; + curScale[kDmgBullet] -= 20; + curScale[kDmgBurn] -= 200; + curScale[kDmgExplode] -= 60; + curScale[kDmgChoke] = 0; + curScale[kDmgElectric] += 40; + break; + case 8: // snow + case 9: // ice + curScale[kDmgFall] = 8; + curScale[kDmgBullet] -= 20; + curScale[kDmgBurn] -= 100; + curScale[kDmgExplode] -= 50; + curScale[kDmgChoke] = 0; + curScale[kDmgElectric] += 40; + break; + case 10: // leaves + case 12: // plant + curScale[kDmgFall] = 0; + curScale[kDmgBullet] -= 10; + curScale[kDmgBurn] += 70; + curScale[kDmgExplode] += 50; + break; + case 11: // cloth + curScale[kDmgFall] = 8; + curScale[kDmgBullet] -= 10; + curScale[kDmgBurn] += 30; + curScale[kDmgExplode] += 20; + break; + case 14: // lava + curScale[kDmgBurn] = 0; + curScale[kDmgExplode] = 0; + curScale[kDmgChoke] += 30; + break; + } - // finally, scale dmg for difficulty - for (int i = 0; i < kDmgMax; i++) - curScale[i] = MulScale(DudeDifficulty[gGameOptions.nDifficulty], ClipLow(curScale[i], 1), 8); - - //short* dc = curScale; - //if (actor->xspr.rxID == 788) - //viewSetSystemMessage("0: %d, 1: %d, 2: %d, 3: %d, 4: %d, 5: %d, 6: %d", dc[0], dc[1], dc[2], dc[3], dc[4], dc[5], dc[6]); + // finally, scale dmg for difficulty + for (int i = 0; i < kDmgMax; i++) + curScale[i] = MulScale(DudeDifficulty[gGameOptions.nDifficulty], ClipLow(curScale[i], 1), 8); + + //short* dc = curScale; + //if (actor->xspr.rxID == 788) + //viewSetSystemMessage("0: %d, 1: %d, 2: %d, 3: %d, 4: %d, 5: %d, 6: %d", dc[0], dc[1], dc[2], dc[3], dc[4], dc[5], dc[6]); } //--------------------------------------------------------------------------- @@ -1671,25 +1672,25 @@ static void scaleDamage(DBloodActor* actor) static int getDispersionModifier(DBloodActor* actor, int minDisp, int maxDisp) { - // the faster fire rate, the less frames = more dispersion - Seq* pSeq = getSequence(actor->xspr.data2 + 6); - int disp = 1; - if (pSeq != nullptr) - { - int nFrames = pSeq->nFrames; int ticks = pSeq->ticksPerFrame; int shots = 0; - for (int i = 0; i <= pSeq->nFrames; i++) { - if (pSeq->frames[i].trigger) shots++; - } - - disp = (((shots * 1000) / nFrames) / ticks) * 20; - if (gGameOptions.nDifficulty > 0) - disp /= gGameOptions.nDifficulty; + // the faster fire rate, the less frames = more dispersion + Seq* pSeq = getSequence(actor->xspr.data2 + 6); + int disp = 1; + if (pSeq != nullptr) + { + int nFrames = pSeq->nFrames; int ticks = pSeq->ticksPerFrame; int shots = 0; + for (int i = 0; i <= pSeq->nFrames; i++) { + if (pSeq->frames[i].trigger) shots++; + } - //viewSetSystemMessage("DISP: %d FRAMES: %d SHOTS: %d TICKS %d", disp, nFrames, shots, ticks); + disp = (((shots * 1000) / nFrames) / ticks) * 20; + if (gGameOptions.nDifficulty > 0) + disp /= gGameOptions.nDifficulty; - } + //viewSetSystemMessage("DISP: %d FRAMES: %d SHOTS: %d TICKS %d", disp, nFrames, shots, ticks); - return ClipRange(disp, minDisp, maxDisp); + } + + return ClipRange(disp, minDisp, maxDisp); } //--------------------------------------------------------------------------- @@ -1698,33 +1699,33 @@ static int getDispersionModifier(DBloodActor* actor, int minDisp, int maxDisp) // //--------------------------------------------------------------------------- -static int getRangeAttackDist(DBloodActor* actor, int minDist, int maxDist) +static int getRangeAttackDist(DBloodActor* actor, int minDist, int maxDist) { - int yrepeat = actor->spr.yrepeat; - int dist = 0; - int seqId = actor->xspr.data2; - int mul = 550; - int picnum = actor->spr.picnum; - - if (yrepeat > 0) - { - if (seqId >= 0) - { - Seq* pSeq = getSequence(seqId); - if (pSeq) - { - picnum = seqGetTile(&pSeq->frames[0]); - } - } - - dist = tileHeight(picnum) << 8; - if (yrepeat < 64) dist -= (64 - yrepeat) * mul; - else if (yrepeat > 64) dist += (yrepeat - 64) * (mul / 3); - } - - dist = ClipRange(dist, minDist, maxDist); - //viewSetSystemMessage("DIST: %d, SPRHEIGHT: %d: YREPEAT: %d PIC: %d", dist, tileHeight(actor->spr.picnum), yrepeat, picnum); - return dist; + int yrepeat = actor->spr.yrepeat; + int dist = 0; + int seqId = actor->xspr.data2; + int mul = 550; + int picnum = actor->spr.picnum; + + if (yrepeat > 0) + { + if (seqId >= 0) + { + Seq* pSeq = getSequence(seqId); + if (pSeq) + { + picnum = seqGetTile(&pSeq->frames[0]); + } + } + + dist = tileHeight(picnum) << 8; + if (yrepeat < 64) dist -= (64 - yrepeat) * mul; + else if (yrepeat > 64) dist += (yrepeat - 64) * (mul / 3); + } + + dist = ClipRange(dist, minDist, maxDist); + //viewSetSystemMessage("DIST: %d, SPRHEIGHT: %d: YREPEAT: %d PIC: %d", dist, tileHeight(actor->spr.picnum), yrepeat, picnum); + return dist; } //--------------------------------------------------------------------------- @@ -1735,27 +1736,27 @@ static int getRangeAttackDist(DBloodActor* actor, int minDist, int maxDist) int getBaseChanceModifier(int baseChance) { - return ((gGameOptions.nDifficulty > 0) ? baseChance - (0x0500 * gGameOptions.nDifficulty) : baseChance); + return ((gGameOptions.nDifficulty > 0) ? baseChance - (0x0500 * gGameOptions.nDifficulty) : baseChance); } -int getRecoilChance(DBloodActor* actor) +int getRecoilChance(DBloodActor* actor) { - int mass = getSpriteMassBySize(actor); - int baseChance = (!dudeIsMelee(actor) ? 0x8000 : 0x4000); - baseChance = getBaseChanceModifier(baseChance) + actor->xspr.data3; - - int chance = ((baseChance / mass) << 7); - return chance; + int mass = getSpriteMassBySize(actor); + int baseChance = (!dudeIsMelee(actor) ? 0x8000 : 0x4000); + baseChance = getBaseChanceModifier(baseChance) + actor->xspr.data3; + + int chance = ((baseChance / mass) << 7); + return chance; } -int getDodgeChance(DBloodActor* actor) +int getDodgeChance(DBloodActor* actor) { - int mass = getSpriteMassBySize(actor); - int baseChance = (!dudeIsMelee(actor) ? 0x6000 : 0x1000); - baseChance = getBaseChanceModifier(baseChance) + actor->xspr.data3; + int mass = getSpriteMassBySize(actor); + int baseChance = (!dudeIsMelee(actor) ? 0x6000 : 0x1000); + baseChance = getBaseChanceModifier(baseChance) + actor->xspr.data3; - int chance = ((baseChance / mass) << 7); - return chance; + int chance = ((baseChance / mass) << 7); + return chance; } //--------------------------------------------------------------------------- @@ -1766,60 +1767,60 @@ int getDodgeChance(DBloodActor* actor) void dudeLeechOperate(DBloodActor* actor, const EVENT& event) { - if (event.cmd == kCmdOff) - { - actPostSprite(actor, kStatFree); - return; - } + if (event.cmd == kCmdOff) + { + actPostSprite(actor, kStatFree); + return; + } - auto actTarget = actor->GetTarget(); - if (actTarget != nullptr && actTarget != actor->GetOwner()) - { - if (actTarget->spr.statnum == kStatDude && !(actTarget->spr.flags & 32) && actTarget->hasX() && !actor->xspr.stateTimer) - { - if (actTarget->IsPlayerActor()) - { - PLAYER* pPlayer = &gPlayer[actTarget->spr.type - kDudePlayer1]; - if (powerupCheck(pPlayer, kPwUpShadowCloak) > 0) return; - } - int top, bottom; - GetActorExtents(actor, &top, &bottom); - int nType = actTarget->spr.type - kDudeBase; - DUDEINFO* pDudeInfo = &dudeInfo[nType]; - int z1 = (top - actor->spr.pos.Z) - 256; - int x = actTarget->spr.pos.X; int y = actTarget->spr.pos.Y; int z = actTarget->spr.pos.Z; - int nDist = approxDist(x - actor->spr.pos.X, y - actor->spr.pos.Y); - - if (nDist != 0 && cansee(actor->spr.pos.X, actor->spr.pos.Y, top, actor->spr.sector(), x, y, z, actTarget->spr.sector())) - { - int t = DivScale(nDist, 0x1aaaaa, 12); - x += (actTarget->xvel * t) >> 12; - y += (actTarget->yvel * t) >> 12; - int angBak = actor->spr.ang; - actor->spr.ang = getangle(x - actor->spr.pos.X, y - actor->spr.pos.Y); - int dx = bcos(actor->spr.ang); - int dy = bsin(actor->spr.ang); - int tz = actTarget->spr.pos.Z - (actTarget->spr.yrepeat * pDudeInfo->aimHeight) * 4; - int dz = DivScale(tz - top - 256, nDist, 10); - int nMissileType = kMissileLifeLeechAltNormal + (actor->xspr.data3 ? 1 : 0); - int t2; - - if (!actor->xspr.data3) t2 = 120 / 10; - else t2 = (3 * 120) / 10; + auto actTarget = actor->GetTarget(); + if (actTarget != nullptr && actTarget != actor->GetOwner()) + { + if (actTarget->spr.statnum == kStatDude && !(actTarget->spr.flags & 32) && actTarget->hasX() && !actor->xspr.stateTimer) + { + if (actTarget->IsPlayerActor()) + { + PLAYER* pPlayer = &gPlayer[actTarget->spr.type - kDudePlayer1]; + if (powerupCheck(pPlayer, kPwUpShadowCloak) > 0) return; + } + int top, bottom; + GetActorExtents(actor, &top, &bottom); + int nType = actTarget->spr.type - kDudeBase; + DUDEINFO* pDudeInfo = &dudeInfo[nType]; + int z1 = (top - actor->spr.pos.Z) - 256; + int x = actTarget->spr.pos.X; int y = actTarget->spr.pos.Y; int z = actTarget->spr.pos.Z; + int nDist = approxDist(x - actor->spr.pos.X, y - actor->spr.pos.Y); - auto missile = actFireMissile(actor, 0, z1, dx, dy, dz, nMissileType); - if (missile) - { - missile->SetOwner(actor); - actor->xspr.stateTimer = 1; - evPostActor(actor, t2, kCallbackLeechStateTimer); - actor->xspr.data3 = ClipLow(actor->xspr.data3 - 1, 0); - } - actor->spr.ang = angBak; - } - } - - } + if (nDist != 0 && cansee(actor->spr.pos.X, actor->spr.pos.Y, top, actor->spr.sector(), x, y, z, actTarget->spr.sector())) + { + int t = DivScale(nDist, 0x1aaaaa, 12); + x += (actTarget->xvel * t) >> 12; + y += (actTarget->yvel * t) >> 12; + int angBak = actor->spr.ang; + actor->spr.ang = getangle(x - actor->spr.pos.X, y - actor->spr.pos.Y); + int dx = bcos(actor->spr.ang); + int dy = bsin(actor->spr.ang); + int tz = actTarget->spr.pos.Z - (actTarget->spr.yrepeat * pDudeInfo->aimHeight) * 4; + int dz = DivScale(tz - top - 256, nDist, 10); + int nMissileType = kMissileLifeLeechAltNormal + (actor->xspr.data3 ? 1 : 0); + int t2; + + if (!actor->xspr.data3) t2 = 120 / 10; + else t2 = (3 * 120) / 10; + + auto missile = actFireMissile(actor, 0, z1, dx, dy, dz, nMissileType); + if (missile) + { + missile->SetOwner(actor); + actor->xspr.stateTimer = 1; + evPostActor(actor, t2, kCallbackLeechStateTimer); + actor->xspr.data3 = ClipLow(actor->xspr.data3 - 1, 0); + } + actor->spr.ang = angBak; + } + } + + } } //--------------------------------------------------------------------------- @@ -1830,34 +1831,34 @@ void dudeLeechOperate(DBloodActor* actor, const EVENT& event) bool doExplosion(DBloodActor* actor, int nType) { - auto actExplosion = actSpawnSprite(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, kStatExplosion, true); - if (!actExplosion->hasX()) - return false; + auto actExplosion = actSpawnSprite(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, kStatExplosion, true); + if (!actExplosion->hasX()) + return false; - int nSeq = 4; int nSnd = 304; const EXPLOSION* pExpl = &explodeInfo[nType]; - - actExplosion->spr.type = nType; - actExplosion->spr.cstat |= CSTAT_SPRITE_INVISIBLE; - actExplosion->SetOwner(actor); - actExplosion->spr.shade = -127; + int nSeq = 4; int nSnd = 304; const EXPLOSION* pExpl = &explodeInfo[nType]; - actExplosion->spr.yrepeat = actExplosion->spr.xrepeat = pExpl->repeat; + actExplosion->spr.type = nType; + actExplosion->spr.cstat |= CSTAT_SPRITE_INVISIBLE; + actExplosion->SetOwner(actor); + actExplosion->spr.shade = -127; - actExplosion->xspr.data1 = pExpl->ticks; - actExplosion->xspr.data2 = pExpl->quakeEffect; - actExplosion->xspr.data3 = pExpl->flashEffect; + actExplosion->spr.yrepeat = actExplosion->spr.xrepeat = pExpl->repeat; - if (nType == 0) { nSeq = 3; nSnd = 303; } - 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; } - - seqSpawn(nSeq, actExplosion, -1); - sfxPlay3DSound(actExplosion, nSnd, -1, 0); + actExplosion->xspr.data1 = pExpl->ticks; + actExplosion->xspr.data2 = pExpl->quakeEffect; + actExplosion->xspr.data3 = pExpl->flashEffect; - return true; + if (nType == 0) { nSeq = 3; nSnd = 303; } + 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; } + + seqSpawn(nSeq, actExplosion, -1); + sfxPlay3DSound(actExplosion, nSnd, -1, 0); + + return true; } //--------------------------------------------------------------------------- @@ -1867,91 +1868,91 @@ bool doExplosion(DBloodActor* actor, int nType) // //--------------------------------------------------------------------------- -DBloodActor* genDudeSpawn(DBloodActor* source, DBloodActor* actor, int nDist) +DBloodActor* genDudeSpawn(DBloodActor* source, DBloodActor* actor, int nDist) { - auto spawned = actSpawnSprite(actor, kStatDude); - int x, y, z = actor->spr.pos.Z, nAngle = actor->spr.ang, nType = kDudeModernCustom; + auto spawned = actSpawnSprite(actor, kStatDude); + int x, y, z = actor->spr.pos.Z, nAngle = actor->spr.ang, nType = kDudeModernCustom; - if (nDist > 0) - { - - x = actor->spr.pos.X + mulscale30r(Cos(nAngle), nDist); - y = actor->spr.pos.Y + mulscale30r(Sin(nAngle), nDist); - } - else - { - - x = actor->spr.pos.X; - y = actor->spr.pos.Y; + if (nDist > 0) + { - } + x = actor->spr.pos.X + mulscale30r(Cos(nAngle), nDist); + y = actor->spr.pos.Y + mulscale30r(Sin(nAngle), nDist); + } + else + { - spawned->spr.type = nType; spawned->spr.ang = nAngle; - vec3_t pos = { x, y, z }; - SetActor(spawned, &pos); - spawned->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL | CSTAT_SPRITE_BLOOD_BIT1; - spawned->spr.clipdist = dudeInfo[nType - kDudeBase].clipdist; + x = actor->spr.pos.X; + y = actor->spr.pos.Y; - // inherit weapon, seq and sound settings. - spawned->xspr.data1 = source->xspr.data1; - spawned->xspr.data2 = source->xspr.data2; - spawned->xspr.sysData1 = source->xspr.data3; // move sndStartId from data3 to sysData1 - spawned->xspr.data3 = 0; + } - // spawn seq - seqSpawn(genDudeSeqStartId(spawned), spawned, -1); + spawned->spr.type = nType; spawned->spr.ang = nAngle; + vec3_t pos = { x, y, z }; + SetActor(spawned, &pos); + spawned->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL | CSTAT_SPRITE_BLOOD_BIT1; + spawned->spr.clipdist = dudeInfo[nType - kDudeBase].clipdist; - // inherit movement speed. - spawned->xspr.busyTime = source->xspr.busyTime; + // inherit weapon, seq and sound settings. + spawned->xspr.data1 = source->xspr.data1; + spawned->xspr.data2 = source->xspr.data2; + spawned->xspr.sysData1 = source->xspr.data3; // move sndStartId from data3 to sysData1 + spawned->xspr.data3 = 0; - // inherit clipdist? - if (source->spr.clipdist > 0) - spawned->spr.clipdist = source->spr.clipdist; + // spawn seq + seqSpawn(genDudeSeqStartId(spawned), spawned, -1); - // inherit custom hp settings - if (source->xspr.data4 <= 0) spawned->xspr.health = dudeInfo[nType - kDudeBase].startHealth << 4; - else spawned->xspr.health = ClipRange(source->xspr.data4 << 4, 1, 65535); + // inherit movement speed. + spawned->xspr.busyTime = source->xspr.busyTime; + + // inherit clipdist? + if (source->spr.clipdist > 0) + spawned->spr.clipdist = source->spr.clipdist; + + // inherit custom hp settings + if (source->xspr.data4 <= 0) spawned->xspr.health = dudeInfo[nType - kDudeBase].startHealth << 4; + else spawned->xspr.health = ClipRange(source->xspr.data4 << 4, 1, 65535); - if (source->spr.flags & kModernTypeFlag1) - { - switch (source->spr.type) { - case kModernCustomDudeSpawn: - //inherit pal? - if (spawned->spr.pal <= 0) spawned->spr.pal = source->spr.pal; + if (source->spr.flags & kModernTypeFlag1) + { + switch (source->spr.type) { + case kModernCustomDudeSpawn: + //inherit pal? + if (spawned->spr.pal <= 0) spawned->spr.pal = source->spr.pal; - // inherit spawn sprite trigger settings, so designer can count monsters. - spawned->xspr.txID = source->xspr.txID; - spawned->xspr.command = source->xspr.command; - spawned->xspr.triggerOn = source->xspr.triggerOn; - spawned->xspr.triggerOff = source->xspr.triggerOff; + // inherit spawn sprite trigger settings, so designer can count monsters. + spawned->xspr.txID = source->xspr.txID; + spawned->xspr.command = source->xspr.command; + spawned->xspr.triggerOn = source->xspr.triggerOn; + spawned->xspr.triggerOff = source->xspr.triggerOff; - // inherit drop items - spawned->xspr.dropMsg = source->xspr.dropMsg; + // inherit drop items + spawned->xspr.dropMsg = source->xspr.dropMsg; - // inherit required key so it can be dropped - spawned->xspr.key = source->xspr.key; + // inherit required key so it can be dropped + spawned->xspr.key = source->xspr.key; - // inherit dude flags - spawned->xspr.dudeDeaf = source->xspr.dudeDeaf; - spawned->xspr.dudeGuard = source->xspr.dudeGuard; - spawned->xspr.dudeAmbush = source->xspr.dudeAmbush; - spawned->xspr.dudeFlag4 = source->xspr.dudeFlag4; - spawned->xspr.unused1 = source->xspr.unused1; - break; - } - } + // inherit dude flags + spawned->xspr.dudeDeaf = source->xspr.dudeDeaf; + spawned->xspr.dudeGuard = source->xspr.dudeGuard; + spawned->xspr.dudeAmbush = source->xspr.dudeAmbush; + spawned->xspr.dudeFlag4 = source->xspr.dudeFlag4; + spawned->xspr.unused1 = source->xspr.unused1; + break; + } + } - // inherit sprite size (useful for seqs with zero repeats) - if (source->spr.flags & kModernTypeFlag2) - { - spawned->spr.xrepeat = source->spr.xrepeat; - spawned->spr.yrepeat = source->spr.yrepeat; - } + // inherit sprite size (useful for seqs with zero repeats) + if (source->spr.flags & kModernTypeFlag2) + { + spawned->spr.xrepeat = source->spr.xrepeat; + spawned->spr.yrepeat = source->spr.yrepeat; + } - gKillMgr.AddNewKill(1); - aiInitSprite(spawned); - return spawned; + gKillMgr.AddNewKill(1); + aiInitSprite(spawned); + return spawned; } //--------------------------------------------------------------------------- @@ -1960,118 +1961,118 @@ DBloodActor* genDudeSpawn(DBloodActor* source, DBloodActor* actor, int nDist) // //--------------------------------------------------------------------------- -void genDudeTransform(DBloodActor* actor) +void genDudeTransform(DBloodActor* actor) { - if (!actor->hasX()) return; - - auto actIncarnation = getNextIncarnation(actor); - if (actIncarnation == NULL) - { - if (actor->xspr.sysData1 == kGenDudeTransformStatus) actor->xspr.sysData1 = 0; - trTriggerSprite(actor, kCmdOff); - return; - } - - actor->xspr.key = actor->xspr.dropMsg = actor->xspr.locked = 0; + if (!actor->hasX()) return; - // save incarnation's going on and off options - bool triggerOn = actIncarnation->xspr.triggerOn; - bool triggerOff = actIncarnation->xspr.triggerOff; + auto actIncarnation = getNextIncarnation(actor); + if (actIncarnation == NULL) + { + if (actor->xspr.sysData1 == kGenDudeTransformStatus) actor->xspr.sysData1 = 0; + trTriggerSprite(actor, kCmdOff); + return; + } - // then remove it from incarnation so it will not send the commands - actIncarnation->xspr.triggerOn = false; - actIncarnation->xspr.triggerOff = false; + actor->xspr.key = actor->xspr.dropMsg = actor->xspr.locked = 0; - // trigger dude death before transform - trTriggerSprite(actor, kCmdOff); + // save incarnation's going on and off options + bool triggerOn = actIncarnation->xspr.triggerOn; + bool triggerOff = actIncarnation->xspr.triggerOff; - actor->spr.type = actor->spr.inittype = actIncarnation->spr.type; - actor->spr.flags = actIncarnation->spr.flags; - actor->spr.pal = actIncarnation->spr.pal; - actor->spr.shade = actIncarnation->spr.shade; - actor->spr.clipdist = actIncarnation->spr.clipdist; - actor->spr.xrepeat = actIncarnation->spr.xrepeat; - actor->spr.yrepeat = actIncarnation->spr.yrepeat; + // then remove it from incarnation so it will not send the commands + actIncarnation->xspr.triggerOn = false; + actIncarnation->xspr.triggerOff = false; - actor->xspr.txID = actIncarnation->xspr.txID; - actor->xspr.command = actIncarnation->xspr.command; - actor->xspr.triggerOn = triggerOn; - actor->xspr.triggerOff = triggerOff; - actor->xspr.busyTime = actIncarnation->xspr.busyTime; - actor->xspr.waitTime = actIncarnation->xspr.waitTime; + // trigger dude death before transform + trTriggerSprite(actor, kCmdOff); - // inherit respawn properties - actor->xspr.respawn = actIncarnation->xspr.respawn; - actor->xspr.respawnPending = actIncarnation->xspr.respawnPending; + actor->spr.type = actor->spr.inittype = actIncarnation->spr.type; + actor->spr.flags = actIncarnation->spr.flags; + actor->spr.pal = actIncarnation->spr.pal; + actor->spr.shade = actIncarnation->spr.shade; + actor->spr.clipdist = actIncarnation->spr.clipdist; + actor->spr.xrepeat = actIncarnation->spr.xrepeat; + actor->spr.yrepeat = actIncarnation->spr.yrepeat; - actor->xspr.burnTime = 0; - actor->SetBurnSource(nullptr); + actor->xspr.txID = actIncarnation->xspr.txID; + actor->xspr.command = actIncarnation->xspr.command; + actor->xspr.triggerOn = triggerOn; + actor->xspr.triggerOff = triggerOff; + actor->xspr.busyTime = actIncarnation->xspr.busyTime; + actor->xspr.waitTime = actIncarnation->xspr.waitTime; - actor->xspr.data1 = actIncarnation->xspr.data1; - actor->xspr.data2 = actIncarnation->xspr.data2; + // inherit respawn properties + actor->xspr.respawn = actIncarnation->xspr.respawn; + actor->xspr.respawnPending = actIncarnation->xspr.respawnPending; - actor->xspr.sysData1 = actIncarnation->xspr.data3; // soundBase id - actor->xspr.sysData2 = actIncarnation->xspr.data4; // start hp + actor->xspr.burnTime = 0; + actor->SetBurnSource(nullptr); - actor->xspr.dudeGuard = actIncarnation->xspr.dudeGuard; - actor->xspr.dudeDeaf = actIncarnation->xspr.dudeDeaf; - actor->xspr.dudeAmbush = actIncarnation->xspr.dudeAmbush; - actor->xspr.dudeFlag4 = actIncarnation->xspr.dudeFlag4; - actor->xspr.unused1 = actIncarnation->xspr.unused1; + actor->xspr.data1 = actIncarnation->xspr.data1; + actor->xspr.data2 = actIncarnation->xspr.data2; - actor->xspr.dropMsg = actIncarnation->xspr.dropMsg; - actor->xspr.key = actIncarnation->xspr.key; + actor->xspr.sysData1 = actIncarnation->xspr.data3; // soundBase id + actor->xspr.sysData2 = actIncarnation->xspr.data4; // start hp - actor->xspr.locked = actIncarnation->xspr.locked; - actor->xspr.Decoupled = actIncarnation->xspr.Decoupled; + actor->xspr.dudeGuard = actIncarnation->xspr.dudeGuard; + actor->xspr.dudeDeaf = actIncarnation->xspr.dudeDeaf; + actor->xspr.dudeAmbush = actIncarnation->xspr.dudeAmbush; + actor->xspr.dudeFlag4 = actIncarnation->xspr.dudeFlag4; + actor->xspr.unused1 = actIncarnation->xspr.unused1; - // clear drop items of the incarnation - actIncarnation->xspr.key = actIncarnation->xspr.dropMsg = 0; + actor->xspr.dropMsg = actIncarnation->xspr.dropMsg; + actor->xspr.key = actIncarnation->xspr.key; - // set hp - if (actor->xspr.sysData2 <= 0) actor->xspr.health = dudeInfo[actor->spr.type - kDudeBase].startHealth << 4; - else actor->xspr.health = ClipRange(actor->xspr.sysData2 << 4, 1, 65535); + actor->xspr.locked = actIncarnation->xspr.locked; + actor->xspr.Decoupled = actIncarnation->xspr.Decoupled; - int seqId = dudeInfo[actor->spr.type - kDudeBase].seqStartID; - switch (actor->spr.type) { - case kDudePodMother: // fake dude - case kDudeTentacleMother: // fake dude - break; - case kDudeModernCustom: - case kDudeModernCustomBurning: - seqId = genDudeSeqStartId(actor); - genDudePrepare(actor, kGenDudePropertyMass); - [[fallthrough]]; // go below - default: - seqSpawn(seqId, actor, -1); + // clear drop items of the incarnation + actIncarnation->xspr.key = actIncarnation->xspr.dropMsg = 0; - // save target - auto target = actor->GetTarget(); + // set hp + if (actor->xspr.sysData2 <= 0) actor->xspr.health = dudeInfo[actor->spr.type - kDudeBase].startHealth << 4; + else actor->xspr.health = ClipRange(actor->xspr.sysData2 << 4, 1, 65535); - // re-init sprite - aiInitSprite(actor); + int seqId = dudeInfo[actor->spr.type - kDudeBase].seqStartID; + switch (actor->spr.type) { + case kDudePodMother: // fake dude + case kDudeTentacleMother: // fake dude + break; + case kDudeModernCustom: + case kDudeModernCustomBurning: + seqId = genDudeSeqStartId(actor); + genDudePrepare(actor, kGenDudePropertyMass); + [[fallthrough]]; // go below + default: + seqSpawn(seqId, actor, -1); - // try to restore target - if (target == nullptr) aiSetTarget(actor, actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z); - else aiSetTarget(actor, target); + // save target + auto target = actor->GetTarget(); - // finally activate it - aiActivateDude(actor); + // re-init sprite + aiInitSprite(actor); - break; - } - actIncarnation->xspr.triggerOn = triggerOn; - actIncarnation->xspr.triggerOff = triggerOff; + // try to restore target + if (target == nullptr) aiSetTarget(actor, actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z); + else aiSetTarget(actor, target); - /*// remove the incarnation in case if non-locked - if (actIncarnation->xspr.locked == 0) { - actIncarnation->xspr.txID = actIncarnation->spr.type = 0; - actPostSprite(pIncarnation, kStatFree); - // or restore triggerOn and off options - } else { - actIncarnation->xspr.triggerOn = triggerOn; - actIncarnation->xspr.triggerOff = triggerOff; - }*/ + // finally activate it + aiActivateDude(actor); + + break; + } + actIncarnation->xspr.triggerOn = triggerOn; + actIncarnation->xspr.triggerOff = triggerOff; + + /*// remove the incarnation in case if non-locked + if (actIncarnation->xspr.locked == 0) { + actIncarnation->xspr.txID = actIncarnation->spr.type = 0; + actPostSprite(pIncarnation, kStatFree); + // or restore triggerOn and off options + } else { + actIncarnation->xspr.triggerOn = triggerOn; + actIncarnation->xspr.triggerOff = triggerOff; + }*/ } //--------------------------------------------------------------------------- @@ -2082,26 +2083,26 @@ void genDudeTransform(DBloodActor* actor) void updateTargetOfLeech(DBloodActor* actor) { - if (!actor->hasX()) return; + if (!actor->hasX()) return; - auto actLeech = leechIsDropped(actor); - if (actLeech == NULL || !actLeech->hasX()) actor->genDudeExtra.pLifeLeech = nullptr; - else - { - if (actor->GetTarget() != actLeech->GetTarget()) - { - if (actor->GetTarget() == nullptr && actLeech->GetTarget() != nullptr) - { - aiSetTarget(actor, actLeech->GetTarget()); - if (inIdle(actor->xspr.aiState)) - aiActivateDude(actor); - } - else - { - actLeech->SetTarget(actor->GetTarget()); - } - } - } + auto actLeech = leechIsDropped(actor); + if (actLeech == NULL || !actLeech->hasX()) actor->genDudeExtra.pLifeLeech = nullptr; + else + { + if (actor->GetTarget() != actLeech->GetTarget()) + { + if (actor->GetTarget() == nullptr && actLeech->GetTarget() != nullptr) + { + aiSetTarget(actor, actLeech->GetTarget()); + if (inIdle(actor->xspr.aiState)) + aiActivateDude(actor); + } + else + { + actLeech->SetTarget(actor->GetTarget()); + } + } + } } //--------------------------------------------------------------------------- @@ -2112,47 +2113,47 @@ void updateTargetOfLeech(DBloodActor* actor) void updateTargetOfSlaves(DBloodActor* actor) { - if (!actor->hasX()) return; + if (!actor->hasX()) return; - GENDUDEEXTRA* pExtra = &actor->genDudeExtra; - auto slave = pExtra->slave; - auto actTarget = actor->GetTarget(); - if (!actTarget || !actTarget->IsDudeActor() || !actTarget->hasX() || actTarget->xspr.health <= 0) actTarget = nullptr; + GENDUDEEXTRA* pExtra = &actor->genDudeExtra; + auto slave = pExtra->slave; + auto actTarget = actor->GetTarget(); + if (!actTarget || !actTarget->IsDudeActor() || !actTarget->hasX() || actTarget->xspr.health <= 0) actTarget = nullptr; - for (int i = 0; i <= gGameOptions.nDifficulty; i++) - { - if (slave[i] != nullptr) - { - if (!slave[i]->IsDudeActor() || !slave[i]->hasX() || slave[i]->xspr.health <= 0) - { - slave[i]->SetOwner(nullptr); - slave[i] = nullptr; - continue; - } + for (int i = 0; i <= gGameOptions.nDifficulty; i++) + { + if (slave[i] != nullptr) + { + if (!slave[i]->IsDudeActor() || !slave[i]->hasX() || slave[i]->xspr.health <= 0) + { + slave[i]->SetOwner(nullptr); + slave[i] = nullptr; + continue; + } - if (actTarget != nullptr) - { - if (actTarget != slave[i]->GetTarget()) aiSetTarget(slave[i], actTarget); - // check if slave have proper target - if (slave[i]->GetTarget() == nullptr || slave[i]->GetTarget()->GetOwner() == actor) - aiSetTarget(slave[i], actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z); - } - else - { - aiSetTarget(slave[i], actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z); // try return to master - } - } - } - // compact the array after processing. - int writeindex = 0; - for (int i = 0; i <= gGameOptions.nDifficulty; i++) - { - if (slave[i] != nullptr) - { - slave[writeindex++] = slave[i]; - } - } - pExtra->slaveCount = writeindex; + if (actTarget != nullptr) + { + if (actTarget != slave[i]->GetTarget()) aiSetTarget(slave[i], actTarget); + // check if slave have proper target + if (slave[i]->GetTarget() == nullptr || slave[i]->GetTarget()->GetOwner() == actor) + aiSetTarget(slave[i], actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z); + } + else + { + aiSetTarget(slave[i], actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z); // try return to master + } + } + } + // compact the array after processing. + int writeindex = 0; + for (int i = 0; i <= gGameOptions.nDifficulty; i++) + { + if (slave[i] != nullptr) + { + slave[writeindex++] = slave[i]; + } + } + pExtra->slaveCount = writeindex; } //--------------------------------------------------------------------------- @@ -2163,56 +2164,56 @@ void updateTargetOfSlaves(DBloodActor* actor) int inDodge(AISTATE* aiState) { - if (aiState == &genDudeDodgeL) return 1; - else if (aiState == &genDudeDodgeD) return 2; - else if (aiState == &genDudeDodgeW) return 3; - else if (aiState == &genDudeDodgeShortL) return 4; - else if (aiState == &genDudeDodgeShortD) return 5; - else if (aiState == &genDudeDodgeShortW) return 6; - else if (aiState == &genDudeDodgeShorterL) return 7; - else if (aiState == &genDudeDodgeShorterD) return 8; - else if (aiState == &genDudeDodgeShorterW) return 9; - return 0; + if (aiState == &genDudeDodgeL) return 1; + else if (aiState == &genDudeDodgeD) return 2; + else if (aiState == &genDudeDodgeW) return 3; + else if (aiState == &genDudeDodgeShortL) return 4; + else if (aiState == &genDudeDodgeShortD) return 5; + else if (aiState == &genDudeDodgeShortW) return 6; + else if (aiState == &genDudeDodgeShorterL) return 7; + else if (aiState == &genDudeDodgeShorterD) return 8; + else if (aiState == &genDudeDodgeShorterW) return 9; + return 0; } bool inIdle(AISTATE* aiState) { - return (aiState == &genDudeIdleW || aiState == &genDudeIdleL); + return (aiState == &genDudeIdleW || aiState == &genDudeIdleL); } bool inAttack(AISTATE* aiState) { - return (aiState == &genDudeFireL || aiState == &genDudeFireW - || aiState == &genDudeFireD || aiState == &genDudeThrow || aiState == &genDudeThrow2 || aiState == &genDudePunch); + return (aiState == &genDudeFireL || aiState == &genDudeFireW + || aiState == &genDudeFireD || aiState == &genDudeThrow || aiState == &genDudeThrow2 || aiState == &genDudePunch); } bool inSearch(AISTATE* aiState) { - return (aiState->stateType == kAiStateSearch); + return (aiState->stateType == kAiStateSearch); } int inChase(AISTATE* aiState) { - if (aiState == &genDudeChaseL) return 1; - else if (aiState == &genDudeChaseD) return 2; - else if (aiState == &genDudeChaseW) return 3; - else if (aiState == &genDudeChaseNoWalkL) return 4; - else if (aiState == &genDudeChaseNoWalkD) return 5; - else if (aiState == &genDudeChaseNoWalkW) return 6; - else return 0; + if (aiState == &genDudeChaseL) return 1; + else if (aiState == &genDudeChaseD) return 2; + else if (aiState == &genDudeChaseW) return 3; + else if (aiState == &genDudeChaseNoWalkL) return 4; + else if (aiState == &genDudeChaseNoWalkD) return 5; + else if (aiState == &genDudeChaseNoWalkW) return 6; + else return 0; } int inRecoil(AISTATE* aiState) { - if (aiState == &genDudeRecoilL || aiState == &genDudeRecoilTesla) return 1; - else if (aiState == &genDudeRecoilD) return 2; - else if (aiState == &genDudeRecoilW) return 3; - else return 0; + if (aiState == &genDudeRecoilL || aiState == &genDudeRecoilTesla) return 1; + else if (aiState == &genDudeRecoilD) return 2; + else if (aiState == &genDudeRecoilW) return 3; + else return 0; } int inDuck(AISTATE* aiState) { - if (aiState == &genDudeFireD) return 1; - else if (aiState == &genDudeChaseD) return 2; - else if (aiState == &genDudeChaseNoWalkD) return 3; - else if (aiState == &genDudeRecoilD) return 4; - else if (aiState == &genDudeDodgeShortD) return 5; - return 0; + if (aiState == &genDudeFireD) return 1; + else if (aiState == &genDudeChaseD) return 2; + else if (aiState == &genDudeChaseNoWalkD) return 3; + else if (aiState == &genDudeRecoilD) return 4; + else if (aiState == &genDudeDodgeShortD) return 5; + return 0; } @@ -2222,19 +2223,19 @@ int inDuck(AISTATE* aiState) { // //--------------------------------------------------------------------------- -bool canSwim(DBloodActor* actor) +bool canSwim(DBloodActor* actor) { - return actor->genDudeExtra.canSwim; + return actor->genDudeExtra.canSwim; } -bool canDuck(DBloodActor* actor) +bool canDuck(DBloodActor* actor) { - return actor->genDudeExtra.canDuck; + return actor->genDudeExtra.canDuck; } -bool canWalk(DBloodActor* actor) +bool canWalk(DBloodActor* actor) { - return actor->genDudeExtra.canWalk; + return actor->genDudeExtra.canWalk; } //--------------------------------------------------------------------------- @@ -2243,253 +2244,254 @@ bool canWalk(DBloodActor* actor) // //--------------------------------------------------------------------------- -int genDudeSeqStartId(DBloodActor* actor) +int genDudeSeqStartId(DBloodActor* actor) { - if (genDudePrepare(actor, kGenDudePropertyStates)) return actor->xspr.data2; - else return kGenDudeDefaultSeq; + if (genDudePrepare(actor, kGenDudePropertyStates)) return actor->xspr.data2; + else return kGenDudeDefaultSeq; } -bool genDudePrepare(DBloodActor* actor, int propId) +bool genDudePrepare(DBloodActor* actor, int propId) { - if (!actor || !actor->hasX()) return false; + if (!actor || !actor->hasX()) return false; - if (actor->spr.type != kDudeModernCustom) { - Printf(PRINT_HIGH, "actor->spr.type != kDudeModernCustom"); - return false; - } else if (propId < kGenDudePropertyAll || propId >= kGenDudePropertyMax) { - viewSetSystemMessage("Unknown custom dude #%d property (%d)", actor->GetIndex(), propId); - return false; - } - - GENDUDEEXTRA* pExtra = &actor->genDudeExtra; - pExtra->updReq[propId] = false; - - switch (propId) { - case kGenDudePropertyAll: - case kGenDudePropertyInitVals: - pExtra->moveSpeed = getGenDudeMoveSpeed(actor, 0, true, false); - pExtra->initVals[0] = actor->spr.xrepeat; - pExtra->initVals[1] = actor->spr.yrepeat; - pExtra->initVals[2] = actor->spr.clipdist; - if (propId) break; - [[fallthrough]]; + if (actor->spr.type != kDudeModernCustom) { + Printf(PRINT_HIGH, "actor->spr.type != kDudeModernCustom"); + return false; + } + else if (propId < kGenDudePropertyAll || propId >= kGenDudePropertyMax) { + viewSetSystemMessage("Unknown custom dude #%d property (%d)", actor->GetIndex(), propId); + return false; + } - case kGenDudePropertyWeapon: { - pExtra->curWeapon = actor->xspr.data1; - switch (actor->xspr.data1) { - case VECTOR_TYPE_19: pExtra->curWeapon = kVectorBullet; break; - case kMissileUnused: pExtra->curWeapon = kMissileArcGargoyle; break; - case kThingDroppedLifeLeech: pExtra->curWeapon = kModernThingEnemyLifeLeech; break; - } + GENDUDEEXTRA* pExtra = &actor->genDudeExtra; + pExtra->updReq[propId] = false; - pExtra->canAttack = false; - if (pExtra->curWeapon > 0 && getSequence(actor->xspr.data2 + kGenDudeSeqAttackNormalL)) - pExtra->canAttack = true; - - pExtra->weaponType = kGenDudeWeaponNone; - if (pExtra->curWeapon > 0 && pExtra->curWeapon < kVectorMax) pExtra->weaponType = kGenDudeWeaponHitscan; - else if (pExtra->curWeapon >= kDudeBase && pExtra->curWeapon < kDudeMax) pExtra->weaponType = kGenDudeWeaponSummon; - else if (pExtra->curWeapon >= kMissileBase && pExtra->curWeapon < kMissileMax) pExtra->weaponType = kGenDudeWeaponMissile; - else if (pExtra->curWeapon >= kThingBase && pExtra->curWeapon < kThingMax) pExtra->weaponType = kGenDudeWeaponThrow; - else if (pExtra->curWeapon >= kTrapExploder && pExtra->curWeapon < (kTrapExploder + kExplodeMax) - 1) - pExtra->weaponType = kGenDudeWeaponKamikaze; - - pExtra->isMelee = false; - if (pExtra->weaponType == kGenDudeWeaponKamikaze) pExtra->isMelee = true; - else if (pExtra->weaponType == kGenDudeWeaponHitscan) { - if (gVectorData[pExtra->curWeapon].maxDist > 0 && gVectorData[pExtra->curWeapon].maxDist <= kGenDudeMaxMeleeDist) - pExtra->isMelee = true; - } + switch (propId) { + case kGenDudePropertyAll: + case kGenDudePropertyInitVals: + pExtra->moveSpeed = getGenDudeMoveSpeed(actor, 0, true, false); + pExtra->initVals[0] = actor->spr.xrepeat; + pExtra->initVals[1] = actor->spr.yrepeat; + pExtra->initVals[2] = actor->spr.clipdist; + if (propId) break; + [[fallthrough]]; - if (propId) break; - [[fallthrough]]; + case kGenDudePropertyWeapon: { + pExtra->curWeapon = actor->xspr.data1; + switch (actor->xspr.data1) { + case VECTOR_TYPE_19: pExtra->curWeapon = kVectorBullet; break; + case kMissileUnused: pExtra->curWeapon = kMissileArcGargoyle; break; + case kThingDroppedLifeLeech: pExtra->curWeapon = kModernThingEnemyLifeLeech; break; + } - } - case kGenDudePropertyDmgScale: - scaleDamage(actor); - if (propId) break; - [[fallthrough]]; + pExtra->canAttack = false; + if (pExtra->curWeapon > 0 && getSequence(actor->xspr.data2 + kGenDudeSeqAttackNormalL)) + pExtra->canAttack = true; - case kGenDudePropertyMass: { - // to ensure mass gets updated, let's clear all cache - SPRITEMASS* pMass = &actor->spriteMass; - pMass->seqId = pMass->picnum = pMass->xrepeat = pMass->yrepeat = pMass->clipdist = 0; - pMass->mass = pMass->airVel = pMass->fraction = 0; - getSpriteMassBySize(actor); - if (propId) break; - [[fallthrough]]; - } - case kGenDudePropertyAttack: - pExtra->fireDist = getRangeAttackDist(actor, 3000, 45000); - pExtra->throwDist = pExtra->fireDist; // temp - pExtra->baseDispersion = getDispersionModifier(actor, 200, 3500); - if (propId) break; - [[fallthrough]]; + pExtra->weaponType = kGenDudeWeaponNone; + if (pExtra->curWeapon > 0 && pExtra->curWeapon < kVectorMax) pExtra->weaponType = kGenDudeWeaponHitscan; + else if (pExtra->curWeapon >= kDudeBase && pExtra->curWeapon < kDudeMax) pExtra->weaponType = kGenDudeWeaponSummon; + else if (pExtra->curWeapon >= kMissileBase && pExtra->curWeapon < kMissileMax) pExtra->weaponType = kGenDudeWeaponMissile; + else if (pExtra->curWeapon >= kThingBase && pExtra->curWeapon < kThingMax) pExtra->weaponType = kGenDudeWeaponThrow; + else if (pExtra->curWeapon >= kTrapExploder && pExtra->curWeapon < (kTrapExploder + kExplodeMax) - 1) + pExtra->weaponType = kGenDudeWeaponKamikaze; - case kGenDudePropertyStates: { + pExtra->isMelee = false; + if (pExtra->weaponType == kGenDudeWeaponKamikaze) pExtra->isMelee = true; + else if (pExtra->weaponType == kGenDudeWeaponHitscan) { + if (gVectorData[pExtra->curWeapon].maxDist > 0 && gVectorData[pExtra->curWeapon].maxDist <= kGenDudeMaxMeleeDist) + pExtra->isMelee = true; + } - pExtra->canFly = false; + if (propId) break; + [[fallthrough]]; - // check the animation - int seqStartId = -1; - if (actor->xspr.data2 <= 0) seqStartId = actor->xspr.data2 = getDudeInfo(actor->spr.type)->seqStartID; - else seqStartId = actor->xspr.data2; + } + case kGenDudePropertyDmgScale: + scaleDamage(actor); + if (propId) break; + [[fallthrough]]; - for (int i = seqStartId; i < seqStartId + kGenDudeSeqMax; i++) { - switch (i - seqStartId) { - case kGenDudeSeqIdleL: - case kGenDudeSeqDeathDefault: - case kGenDudeSeqAttackNormalL: - case kGenDudeSeqAttackThrow: - case kGenDudeSeqAttackPunch: - { - Seq* pSeq = getSequence(i); - if (!pSeq) - { - actor->xspr.data2 = getDudeInfo(actor->spr.type)->seqStartID; - viewSetSystemMessage("No SEQ animation id %d found for custom dude #%d!", i, actor->GetIndex()); - viewSetSystemMessage("SEQ base id: %d", seqStartId); - } - else if ((i - seqStartId) == kGenDudeSeqAttackPunch) - { - pExtra->forcePunch = true; // required for those who don't have fire trigger in punch seq and for default animation - for (int ii = 0; ii < pSeq->nFrames; ii++) { - if (!pSeq->frames[ii].trigger) continue; - pExtra->forcePunch = false; - break; - } - } - break; - } - case kGenDudeSeqDeathExplode: - pExtra->availDeaths[kDmgExplode] = !!getSequence(i); - break; - case kGenDudeSeqBurning: - pExtra->canBurn = !!getSequence(i); - break; - case kGenDudeSeqElectocuted: - pExtra->canElectrocute = !!getSequence(i); - break; - case kGenDudeSeqRecoil: - pExtra->canRecoil = !!getSequence(i); - break; - case kGenDudeSeqMoveL: { - bool oldStatus = pExtra->canWalk; - pExtra->canWalk = !!getSequence(i); - if (oldStatus != pExtra->canWalk) { - if (actor->GetTarget() == nullptr) - { - if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeIdleW); - else aiGenDudeNewState(actor, &genDudeIdleL); - } - else if (pExtra->canWalk) - { - if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeChaseW); - else if (inDuck(actor->xspr.aiState)) aiGenDudeNewState(actor, &genDudeChaseD); - else aiGenDudeNewState(actor, &genDudeChaseL); - } - else - { - if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeChaseNoWalkW); - else if (inDuck(actor->xspr.aiState)) aiGenDudeNewState(actor, &genDudeChaseNoWalkD); - else aiGenDudeNewState(actor, &genDudeChaseNoWalkL); - } - } - break; - } - case kGenDudeSeqAttackNormalDW: - pExtra->canDuck = (getSequence(i) && getSequence(seqStartId + 14)); - pExtra->canSwim = (getSequence(i) && getSequence(seqStartId + 13) - && getSequence(seqStartId + 17)); - break; - case kGenDudeSeqDeathBurn1: { - bool seq15 = getSequence(i); - bool seq16 = getSequence(seqStartId + 16); - if (seq15 && seq16) pExtra->availDeaths[kDmgBurn] = 3; - else if (seq16) pExtra->availDeaths[kDmgBurn] = 2; - else if (seq15) pExtra->availDeaths[kDmgBurn] = 1; - else pExtra->availDeaths[kDmgBurn] = 0; - break; - } - case kGenDudeSeqMoveW: - case kGenDudeSeqMoveD: - case kGenDudeSeqDeathBurn2: - case kGenDudeSeqIdleW: - break; - case kGenDudeSeqReserved3: - case kGenDudeSeqReserved4: - case kGenDudeSeqReserved5: - case kGenDudeSeqReserved6: - case kGenDudeSeqReserved7: - case kGenDudeSeqReserved8: - /*if (getSequence(i)) { - viewSetSystemMessage("Found reserved SEQ animation (%d) for custom dude #%d!", i, actor->GetIndex()); - viewSetSystemMessage("Using reserved animation is not recommended."); - viewSetSystemMessage("SEQ base id: %d", seqStartId); - }*/ - break; - } - } - if (propId) break; - [[fallthrough]]; - } - case kGenDudePropertyLeech: - pExtra->pLifeLeech = nullptr; - if (!actor->GetSpecialOwner()) - { - BloodStatIterator it(kStatThing); - while (auto actor2 = it.Next()) - { - if (actor2->GetOwner() == actor && actor2->spr.type == kModernThingEnemyLifeLeech) { - pExtra->pLifeLeech = actor2; - break; - } - } - } - if (propId) break; - [[fallthrough]]; + case kGenDudePropertyMass: { + // to ensure mass gets updated, let's clear all cache + SPRITEMASS* pMass = &actor->spriteMass; + pMass->seqId = pMass->picnum = pMass->xrepeat = pMass->yrepeat = pMass->clipdist = 0; + pMass->mass = pMass->airVel = pMass->fraction = 0; + getSpriteMassBySize(actor); + if (propId) break; + [[fallthrough]]; + } + case kGenDudePropertyAttack: + pExtra->fireDist = getRangeAttackDist(actor, 3000, 45000); + pExtra->throwDist = pExtra->fireDist; // temp + pExtra->baseDispersion = getDispersionModifier(actor, 200, 3500); + if (propId) break; + [[fallthrough]]; - case kGenDudePropertySlaves: - { - pExtra->slaveCount = 0; - for (auto i = 0; i < kGenDudeMaxSlaves; i++) - { - pExtra->slave[i] = nullptr; - } + case kGenDudePropertyStates: { - BloodStatIterator it(kStatDude); - while (auto actor2 = it.Next()) - { - if (actor2->GetOwner() != actor) continue; - else if (!actor2->IsDudeActor() || !actor2->hasX() || actor2->xspr.health <= 0) { - actor2->SetOwner(nullptr); - continue; - } + pExtra->canFly = false; - pExtra->slave[pExtra->slaveCount++] = actor2; - if (pExtra->slaveCount > gGameOptions.nDifficulty) - break; - } - if (propId) break; - [[fallthrough]]; - } - case kGenDudePropertySpriteSize: { - if (seqGetStatus(actor) == -1) - seqSpawn(actor->xspr.data2 + actor->xspr.aiState->seqId, actor, -1); + // check the animation + int seqStartId = -1; + if (actor->xspr.data2 <= 0) seqStartId = actor->xspr.data2 = getDudeInfo(actor->spr.type)->seqStartID; + else seqStartId = actor->xspr.data2; - // make sure dudes aren't in the floor or ceiling - int zTop, zBot; GetActorExtents(actor, &zTop, &zBot); - if (!(actor->spr.sector()->ceilingstat & CSTAT_SECTOR_SKY)) - actor->spr.pos.Z += ClipLow(actor->spr.sector()->ceilingz - zTop, 0); - if (!(actor->spr.sector()->floorstat & CSTAT_SECTOR_SKY)) - actor->spr.pos.Z += ClipHigh(actor->spr.sector()->floorz - zBot, 0); + for (int i = seqStartId; i < seqStartId + kGenDudeSeqMax; i++) { + switch (i - seqStartId) { + case kGenDudeSeqIdleL: + case kGenDudeSeqDeathDefault: + case kGenDudeSeqAttackNormalL: + case kGenDudeSeqAttackThrow: + case kGenDudeSeqAttackPunch: + { + Seq* pSeq = getSequence(i); + if (!pSeq) + { + actor->xspr.data2 = getDudeInfo(actor->spr.type)->seqStartID; + viewSetSystemMessage("No SEQ animation id %d found for custom dude #%d!", i, actor->GetIndex()); + viewSetSystemMessage("SEQ base id: %d", seqStartId); + } + else if ((i - seqStartId) == kGenDudeSeqAttackPunch) + { + pExtra->forcePunch = true; // required for those who don't have fire trigger in punch seq and for default animation + for (int ii = 0; ii < pSeq->nFrames; ii++) { + if (!pSeq->frames[ii].trigger) continue; + pExtra->forcePunch = false; + break; + } + } + break; + } + case kGenDudeSeqDeathExplode: + pExtra->availDeaths[kDmgExplode] = !!getSequence(i); + break; + case kGenDudeSeqBurning: + pExtra->canBurn = !!getSequence(i); + break; + case kGenDudeSeqElectocuted: + pExtra->canElectrocute = !!getSequence(i); + break; + case kGenDudeSeqRecoil: + pExtra->canRecoil = !!getSequence(i); + break; + case kGenDudeSeqMoveL: { + bool oldStatus = pExtra->canWalk; + pExtra->canWalk = !!getSequence(i); + if (oldStatus != pExtra->canWalk) { + if (actor->GetTarget() == nullptr) + { + if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeIdleW); + else aiGenDudeNewState(actor, &genDudeIdleL); + } + else if (pExtra->canWalk) + { + if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeChaseW); + else if (inDuck(actor->xspr.aiState)) aiGenDudeNewState(actor, &genDudeChaseD); + else aiGenDudeNewState(actor, &genDudeChaseL); + } + else + { + if (spriteIsUnderwater(actor, false)) aiGenDudeNewState(actor, &genDudeChaseNoWalkW); + else if (inDuck(actor->xspr.aiState)) aiGenDudeNewState(actor, &genDudeChaseNoWalkD); + else aiGenDudeNewState(actor, &genDudeChaseNoWalkL); + } + } + break; + } + case kGenDudeSeqAttackNormalDW: + pExtra->canDuck = (getSequence(i) && getSequence(seqStartId + 14)); + pExtra->canSwim = (getSequence(i) && getSequence(seqStartId + 13) + && getSequence(seqStartId + 17)); + break; + case kGenDudeSeqDeathBurn1: { + bool seq15 = getSequence(i); + bool seq16 = getSequence(seqStartId + 16); + if (seq15 && seq16) pExtra->availDeaths[kDmgBurn] = 3; + else if (seq16) pExtra->availDeaths[kDmgBurn] = 2; + else if (seq15) pExtra->availDeaths[kDmgBurn] = 1; + else pExtra->availDeaths[kDmgBurn] = 0; + break; + } + case kGenDudeSeqMoveW: + case kGenDudeSeqMoveD: + case kGenDudeSeqDeathBurn2: + case kGenDudeSeqIdleW: + break; + case kGenDudeSeqReserved3: + case kGenDudeSeqReserved4: + case kGenDudeSeqReserved5: + case kGenDudeSeqReserved6: + case kGenDudeSeqReserved7: + case kGenDudeSeqReserved8: + /*if (getSequence(i)) { + viewSetSystemMessage("Found reserved SEQ animation (%d) for custom dude #%d!", i, actor->GetIndex()); + viewSetSystemMessage("Using reserved animation is not recommended."); + viewSetSystemMessage("SEQ base id: %d", seqStartId); + }*/ + break; + } + } + if (propId) break; + [[fallthrough]]; + } + case kGenDudePropertyLeech: + pExtra->pLifeLeech = nullptr; + if (!actor->GetSpecialOwner()) + { + BloodStatIterator it(kStatThing); + while (auto actor2 = it.Next()) + { + if (actor2->GetOwner() == actor && actor2->spr.type == kModernThingEnemyLifeLeech) { + pExtra->pLifeLeech = actor2; + break; + } + } + } + if (propId) break; + [[fallthrough]]; - actor->spr.clipdist = ClipRange((actor->spr.xrepeat + actor->spr.yrepeat) >> 1, 4, 120); - if (propId) break; - } - } + case kGenDudePropertySlaves: + { + pExtra->slaveCount = 0; + for (auto i = 0; i < kGenDudeMaxSlaves; i++) + { + pExtra->slave[i] = nullptr; + } - return true; + BloodStatIterator it(kStatDude); + while (auto actor2 = it.Next()) + { + if (actor2->GetOwner() != actor) continue; + else if (!actor2->IsDudeActor() || !actor2->hasX() || actor2->xspr.health <= 0) { + actor2->SetOwner(nullptr); + continue; + } + + pExtra->slave[pExtra->slaveCount++] = actor2; + if (pExtra->slaveCount > gGameOptions.nDifficulty) + break; + } + if (propId) break; + [[fallthrough]]; + } + case kGenDudePropertySpriteSize: { + if (seqGetStatus(actor) == -1) + seqSpawn(actor->xspr.data2 + actor->xspr.aiState->seqId, actor, -1); + + // make sure dudes aren't in the floor or ceiling + int zTop, zBot; GetActorExtents(actor, &zTop, &zBot); + if (!(actor->spr.sector()->ceilingstat & CSTAT_SECTOR_SKY)) + actor->spr.pos.Z += ClipLow(actor->spr.sector()->ceilingz - zTop, 0); + if (!(actor->spr.sector()->floorstat & CSTAT_SECTOR_SKY)) + actor->spr.pos.Z += ClipHigh(actor->spr.sector()->floorz - zBot, 0); + + actor->spr.clipdist = ClipRange((actor->spr.xrepeat + actor->spr.yrepeat) >> 1, 4, 120); + if (propId) break; + } + } + + return true; } //--------------------------------------------------------------------------- @@ -2498,23 +2500,23 @@ bool genDudePrepare(DBloodActor* actor, int propId) // //--------------------------------------------------------------------------- -void genDudePostDeath(DBloodActor* actor, DAMAGE_TYPE damageType, int damage) +void genDudePostDeath(DBloodActor* actor, DAMAGE_TYPE damageType, int damage) { - if (damageType == kDamageExplode) - { - DUDEINFO* pDudeInfo = getDudeInfo(actor->spr.type); - for (int i = 0; i < 3; i++) - if (pDudeInfo->nGibType[i] > -1) - GibSprite(actor, (GIBTYPE)pDudeInfo->nGibType[i], NULL, NULL); + if (damageType == kDamageExplode) + { + DUDEINFO* pDudeInfo = getDudeInfo(actor->spr.type); + for (int i = 0; i < 3; i++) + if (pDudeInfo->nGibType[i] > -1) + GibSprite(actor, (GIBTYPE)pDudeInfo->nGibType[i], NULL, NULL); - for (int i = 0; i < 4; i++) - fxSpawnBlood(actor, damage); - } - - gKillMgr.AddKill(actor); + for (int i = 0; i < 4; i++) + fxSpawnBlood(actor, damage); + } - actor->spr.type = kThingBloodChunks; - actPostSprite(actor, kStatThing); + gKillMgr.AddKill(actor); + + actor->spr.type = kThingBloodChunks; + actPostSprite(actor, kStatThing); } //--------------------------------------------------------------------------- @@ -2525,23 +2527,23 @@ void genDudePostDeath(DBloodActor* actor, DAMAGE_TYPE damageType, int damage) void aiGenDudeInitSprite(DBloodActor* actor) { - switch (actor->spr.type) - { - case kDudeModernCustom: - { - DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; - pDudeExtraE->active = 0; - aiGenDudeNewState(actor, &genDudeIdleL); - break; - } - case kDudeModernCustomBurning: - aiGenDudeNewState(actor, &genDudeBurnGoto); - actor->xspr.burnTime = 1200; - break; - } - - actor->spr.flags = 15; - return; + switch (actor->spr.type) + { + case kDudeModernCustom: + { + DUDEEXTRA_STATS* pDudeExtraE = &actor->dudeExtra.stats; + pDudeExtraE->active = 0; + aiGenDudeNewState(actor, &genDudeIdleL); + break; + } + case kDudeModernCustomBurning: + aiGenDudeNewState(actor, &genDudeBurnGoto); + actor->xspr.burnTime = 1200; + break; + } + + actor->spr.flags = 15; + return; } END_BLD_NS diff --git a/source/games/blood/src/animatesprite.cpp b/source/games/blood/src/animatesprite.cpp index 6a84bf91d..325652eda 100644 --- a/source/games/blood/src/animatesprite.cpp +++ b/source/games/blood/src/animatesprite.cpp @@ -45,948 +45,994 @@ BEGIN_BLD_NS static fixed_t gCameraAng; int dword_172CE0[16][3]; -static void RotateYZ(int *, int *pY, int *pZ, int ang) +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void RotateYZ(int*, int* pY, int* pZ, int ang) { int oY, oZ, angSin, angCos; oY = *pY; oZ = *pZ; angSin = Sin(ang); angCos = Cos(ang); - *pY = dmulscale30r(oY,angCos,oZ,-angSin); - *pZ = dmulscale30r(oY,angSin,oZ,angCos); + *pY = dmulscale30r(oY, angCos, oZ, -angSin); + *pZ = dmulscale30r(oY, angSin, oZ, angCos); } -static void RotateXZ(int *pX, int *, int *pZ, int ang) +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void RotateXZ(int* pX, int*, int* pZ, int ang) { int oX, oZ, angSin, angCos; oX = *pX; oZ = *pZ; - angSin = Sin(ang); - angCos = Cos(ang); - *pX = dmulscale30r(oX,angCos,oZ,-angSin); - *pZ = dmulscale30r(oX,angSin,oZ,angCos); + angSin = Sin(ang); + angCos = Cos(ang); + *pX = dmulscale30r(oX, angCos, oZ, -angSin); + *pZ = dmulscale30r(oX, angSin, oZ, angCos); } -tspritetype* viewInsertTSprite(tspritetype* tsprite, int& spritesortcnt, sectortype* pSector, int nStatnum, tspritetype const * const parentTSprite) -{ - if (spritesortcnt >= MAXSPRITESONSCREEN) - return nullptr; +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- - int nTSprite = spritesortcnt; - tspritetype *pTSprite = &tsprite[nTSprite]; - memset(pTSprite, 0, sizeof(tspritetype)); - pTSprite->cstat = CSTAT_SPRITE_YCENTER; - pTSprite->xrepeat = 64; - pTSprite->yrepeat = 64; - pTSprite->ownerActor = nullptr; - pTSprite->type = -spritesortcnt; - pTSprite->statnum = nStatnum; - pTSprite->setsector(pSector); - spritesortcnt++; - if (parentTSprite) - { - pTSprite->pos = parentTSprite->pos; - pTSprite->ownerActor = parentTSprite->ownerActor; - pTSprite->ang = parentTSprite->ang; - } - pTSprite->pos.X += Cos(gCameraAng)>>25; - pTSprite->pos.Y += Sin(gCameraAng)>>25; - return pTSprite; +tspritetype* viewInsertTSprite(tspritetype* tsprite, int& spritesortcnt, sectortype* pSector, int nStatnum, tspritetype const* const parentTSprite) +{ + if (spritesortcnt >= MAXSPRITESONSCREEN) + return nullptr; + + int nTSprite = spritesortcnt; + tspritetype* pTSprite = &tsprite[nTSprite]; + memset(pTSprite, 0, sizeof(tspritetype)); + pTSprite->cstat = CSTAT_SPRITE_YCENTER; + pTSprite->xrepeat = 64; + pTSprite->yrepeat = 64; + pTSprite->ownerActor = nullptr; + pTSprite->type = -spritesortcnt; + pTSprite->statnum = nStatnum; + pTSprite->setsector(pSector); + spritesortcnt++; + if (parentTSprite) + { + pTSprite->pos = parentTSprite->pos; + pTSprite->ownerActor = parentTSprite->ownerActor; + pTSprite->ang = parentTSprite->ang; + } + pTSprite->pos.X += Cos(gCameraAng) >> 25; + pTSprite->pos.Y += Sin(gCameraAng) >> 25; + return pTSprite; } static const int effectDetail[kViewEffectMax] = { - 4, 4, 4, 4, 0, 0, 0, 0, 0, 1, 4, 4, 0, 0, 0, 1, 0, 0, 0 + 4, 4, 4, 4, 0, 0, 0, 0, 0, 1, 4, 4, 0, 0, 0, 1, 0, 0, 0 }; struct WEAPONICON { - int16_t nTile; - uint8_t zOffset; + int16_t nTile; + uint8_t zOffset; }; static const WEAPONICON gWeaponIcon[] = { - { -1, 0 }, - { -1, 0 }, // 1: pitchfork - { 524, 6 }, // 2: flare gun - { 559, 6 }, // 3: shotgun - { 558, 8 }, // 4: tommy gun - { 526, 6 }, // 5: napalm launcher - { 589, 11 }, // 6: dynamite - { 618, 11 }, // 7: spray can - { 539, 6 }, // 8: tesla gun - { 800, 0 }, // 9: life leech - { 525, 11 }, // 10: voodoo doll - { 811, 11 }, // 11: proxy bomb - { 810, 11 }, // 12: remote bomb - { -1, 0 }, + { -1, 0 }, + { -1, 0 }, // 1: pitchfork + { 524, 6 }, // 2: flare gun + { 559, 6 }, // 3: shotgun + { 558, 8 }, // 4: tommy gun + { 526, 6 }, // 5: napalm launcher + { 589, 11 }, // 6: dynamite + { 618, 11 }, // 7: spray can + { 539, 6 }, // 8: tesla gun + { 800, 0 }, // 9: life leech + { 525, 11 }, // 10: voodoo doll + { 811, 11 }, // 11: proxy bomb + { 810, 11 }, // 12: remote bomb + { -1, 0 }, }; -static tspritetype *viewAddEffect(tspritetype* tsprite, int& spritesortcnt, int nTSprite, VIEW_EFFECT nViewEffect) +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static tspritetype* viewAddEffect(tspritetype* tsprite, int& spritesortcnt, int nTSprite, VIEW_EFFECT nViewEffect) { - assert(nViewEffect >= 0 && nViewEffect < kViewEffectMax); - auto pTSprite = &tsprite[nTSprite]; - auto owneractor = static_cast(pTSprite->ownerActor); - if (gDetail < effectDetail[nViewEffect] || nTSprite >= MAXSPRITESONSCREEN) return NULL; - switch (nViewEffect) - { - case kViewEffectSpotProgress: { - int perc = (100 * owneractor->xspr.data3) / kMaxPatrolSpotValue; - int width = (94 * owneractor->xspr.data3) / kMaxPatrolSpotValue; + assert(nViewEffect >= 0 && nViewEffect < kViewEffectMax); + auto pTSprite = &tsprite[nTSprite]; + auto owneractor = static_cast(pTSprite->ownerActor); + if (gDetail < effectDetail[nViewEffect] || nTSprite >= MAXSPRITESONSCREEN) return NULL; + switch (nViewEffect) + { + case kViewEffectSpotProgress: { + int perc = (100 * owneractor->xspr.data3) / kMaxPatrolSpotValue; + int width = (94 * owneractor->xspr.data3) / kMaxPatrolSpotValue; - int top, bottom; - GetSpriteExtents(pTSprite, &top, &bottom); + int top, bottom; + GetSpriteExtents(pTSprite, &top, &bottom); - auto pNSprite2 = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite2) - break; + auto pNSprite2 = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite2) + break; - pNSprite2->picnum = 2203; + pNSprite2->picnum = 2203; - pNSprite2->xrepeat = width; - pNSprite2->yrepeat = 20; - pNSprite2->pal = 10; - if (perc >= 75) pNSprite2->pal = 0; - else if (perc >= 50) pNSprite2->pal = 6; + pNSprite2->xrepeat = width; + pNSprite2->yrepeat = 20; + pNSprite2->pal = 10; + if (perc >= 75) pNSprite2->pal = 0; + else if (perc >= 50) pNSprite2->pal = 6; - pNSprite2->pos.Z = top - 2048; - pNSprite2->shade = -128; - break; - } - case kViewEffectAtom: - for (int i = 0; i < 16; i++) - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + pNSprite2->pos.Z = top - 2048; + pNSprite2->shade = -128; + break; + } + case kViewEffectAtom: + for (int i = 0; i < 16; i++) + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - int ang = (PlayClock*2048)/120; - int nRand1 = dword_172CE0[i][0]; - int nRand2 = dword_172CE0[i][1]; - int nRand3 = dword_172CE0[i][2]; - ang += nRand3; - int x = MulScale(512, Cos(ang), 30); - int y = MulScale(512, Sin(ang), 30); - int z = 0; - RotateYZ(&x, &y, &z, nRand1); - RotateXZ(&x, &y, &z, nRand2); - pNSprite->pos.X = pTSprite->pos.X + x; - pNSprite->pos.Y = pTSprite->pos.Y + y; - pNSprite->pos.Z = pTSprite->pos.Z + (z<<4); - pNSprite->picnum = 1720; - pNSprite->shade = -128; - } - break; - case kViewEffectFlag: - case kViewEffectBigFlag: - { - int top, bottom; - GetSpriteExtents(pTSprite, &top, &bottom); - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + int ang = (PlayClock * 2048) / 120; + int nRand1 = dword_172CE0[i][0]; + int nRand2 = dword_172CE0[i][1]; + int nRand3 = dword_172CE0[i][2]; + ang += nRand3; + int x = MulScale(512, Cos(ang), 30); + int y = MulScale(512, Sin(ang), 30); + int z = 0; + RotateYZ(&x, &y, &z, nRand1); + RotateXZ(&x, &y, &z, nRand2); + pNSprite->pos.X = pTSprite->pos.X + x; + pNSprite->pos.Y = pTSprite->pos.Y + y; + pNSprite->pos.Z = pTSprite->pos.Z + (z << 4); + pNSprite->picnum = 1720; + pNSprite->shade = -128; + } + break; + case kViewEffectFlag: + case kViewEffectBigFlag: + { + int top, bottom; + GetSpriteExtents(pTSprite, &top, &bottom); + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - pNSprite->shade = -128; - pNSprite->pal = 0; - pNSprite->pos.Z = top; - if (nViewEffect == kViewEffectFlag) - pNSprite->xrepeat = pNSprite->yrepeat = 24; - else - pNSprite->xrepeat = pNSprite->yrepeat = 64; - pNSprite->picnum = 3558; - return pNSprite; - } - case kViewEffectTesla: - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + pNSprite->shade = -128; + pNSprite->pal = 0; + pNSprite->pos.Z = top; + if (nViewEffect == kViewEffectFlag) + pNSprite->xrepeat = pNSprite->yrepeat = 24; + else + pNSprite->xrepeat = pNSprite->yrepeat = 64; + pNSprite->picnum = 3558; + return pNSprite; + } + case kViewEffectTesla: + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - pNSprite->pos.Z = pTSprite->pos.Z; - pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; - pNSprite->shade = -128; - pNSprite->xrepeat = pTSprite->xrepeat; - pNSprite->yrepeat = pTSprite->yrepeat; - pNSprite->picnum = 2135; - break; - } - case kViewEffectShoot: - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + pNSprite->pos.Z = pTSprite->pos.Z; + pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; + pNSprite->shade = -128; + pNSprite->xrepeat = pTSprite->xrepeat; + pNSprite->yrepeat = pTSprite->yrepeat; + pNSprite->picnum = 2135; + break; + } + case kViewEffectShoot: + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - pNSprite->shade = -128; - pNSprite->pal = 0; - pNSprite->xrepeat = pNSprite->yrepeat = 64; - pNSprite->picnum = 2605; - return pNSprite; - } - case kViewEffectReflectiveBall: - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + pNSprite->shade = -128; + pNSprite->pal = 0; + pNSprite->xrepeat = pNSprite->yrepeat = 64; + pNSprite->picnum = 2605; + return pNSprite; + } + case kViewEffectReflectiveBall: + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - pNSprite->shade = 26; - pNSprite->pal = 0; - pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; - pNSprite->xrepeat = pNSprite->yrepeat = 64; - pNSprite->picnum = 2089; - break; - } - case kViewEffectPhase: - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + pNSprite->shade = 26; + pNSprite->pal = 0; + pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; + pNSprite->xrepeat = pNSprite->yrepeat = 64; + pNSprite->picnum = 2089; + break; + } + case kViewEffectPhase: + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - int top, bottom; - GetSpriteExtents(pTSprite, &top, &bottom); - pNSprite->shade = 26; - pNSprite->pal = 0; - pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; - pNSprite->xrepeat = pNSprite->yrepeat = 24; - pNSprite->picnum = 626; - pNSprite->pos.Z = top; - break; - } - case kViewEffectTrail: - { - int nAng = pTSprite->ang; - if (pTSprite->cstat & CSTAT_SPRITE_ALIGNMENT_WALL) - { - nAng = (nAng+512)&2047; - } - else - { - nAng = (nAng+1024)&2047; - } - for (int i = 0; i < 5 && spritesortcnt < MAXSPRITESONSCREEN; i++) - { - auto pSector = pTSprite->sector(); - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pSector, 32767, NULL); - if (!pNSprite) - break; + int top, bottom; + GetSpriteExtents(pTSprite, &top, &bottom); + pNSprite->shade = 26; + pNSprite->pal = 0; + pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; + pNSprite->xrepeat = pNSprite->yrepeat = 24; + pNSprite->picnum = 626; + pNSprite->pos.Z = top; + break; + } + case kViewEffectTrail: + { + int nAng = pTSprite->ang; + if (pTSprite->cstat & CSTAT_SPRITE_ALIGNMENT_WALL) + { + nAng = (nAng + 512) & 2047; + } + else + { + nAng = (nAng + 1024) & 2047; + } + for (int i = 0; i < 5 && spritesortcnt < MAXSPRITESONSCREEN; i++) + { + auto pSector = pTSprite->sector(); + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pSector, 32767, NULL); + if (!pNSprite) + break; - int nLen = 128+(i<<7); - int x = MulScale(nLen, Cos(nAng), 30); - pNSprite->pos.X = pTSprite->pos.X + x; - int y = MulScale(nLen, Sin(nAng), 30); - pNSprite->pos.Y = pTSprite->pos.Y + y; - pNSprite->pos.Z = pTSprite->pos.Z; - assert(pSector); - FindSector(pNSprite->pos.X, pNSprite->pos.Y, pNSprite->pos.Z, &pSector); - pNSprite->setsector(pSector); - pNSprite->ownerActor = pTSprite->ownerActor; - pNSprite->picnum = pTSprite->picnum; - pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; - if (i < 2) - pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT | CSTAT_SPRITE_TRANS_FLIP; - pNSprite->shade = ClipLow(pTSprite->shade-16, -128); - pNSprite->xrepeat = pTSprite->xrepeat; - pNSprite->yrepeat = pTSprite->yrepeat; - pNSprite->picnum = pTSprite->picnum; - } - break; - } - case kViewEffectFlame: - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + int nLen = 128 + (i << 7); + int x = MulScale(nLen, Cos(nAng), 30); + pNSprite->pos.X = pTSprite->pos.X + x; + int y = MulScale(nLen, Sin(nAng), 30); + pNSprite->pos.Y = pTSprite->pos.Y + y; + pNSprite->pos.Z = pTSprite->pos.Z; + assert(pSector); + FindSector(pNSprite->pos.X, pNSprite->pos.Y, pNSprite->pos.Z, &pSector); + pNSprite->setsector(pSector); + pNSprite->ownerActor = pTSprite->ownerActor; + pNSprite->picnum = pTSprite->picnum; + pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; + if (i < 2) + pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT | CSTAT_SPRITE_TRANS_FLIP; + pNSprite->shade = ClipLow(pTSprite->shade - 16, -128); + pNSprite->xrepeat = pTSprite->xrepeat; + pNSprite->yrepeat = pTSprite->yrepeat; + pNSprite->picnum = pTSprite->picnum; + } + break; + } + case kViewEffectFlame: + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - pNSprite->shade = -128; - pNSprite->pos.Z = pTSprite->pos.Z; - pNSprite->picnum = 908; - pNSprite->statnum = kStatDecoration; - pNSprite->xrepeat = pNSprite->yrepeat = (tileWidth(pTSprite->picnum)*pTSprite->xrepeat)/64; - break; - } - case kViewEffectSmokeHigh: - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + pNSprite->shade = -128; + pNSprite->pos.Z = pTSprite->pos.Z; + pNSprite->picnum = 908; + pNSprite->statnum = kStatDecoration; + pNSprite->xrepeat = pNSprite->yrepeat = (tileWidth(pTSprite->picnum) * pTSprite->xrepeat) / 64; + break; + } + case kViewEffectSmokeHigh: + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - int top, bottom; - GetSpriteExtents(pTSprite, &top, &bottom); - pNSprite->pos.Z = top; - if (IsDudeSprite(pTSprite)) - pNSprite->picnum = 672; - else - pNSprite->picnum = 754; - pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; - pNSprite->shade = 8; - pNSprite->xrepeat = pTSprite->xrepeat; - pNSprite->yrepeat = pTSprite->yrepeat; - break; - } - case kViewEffectSmokeLow: - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + int top, bottom; + GetSpriteExtents(pTSprite, &top, &bottom); + pNSprite->pos.Z = top; + if (IsDudeSprite(pTSprite)) + pNSprite->picnum = 672; + else + pNSprite->picnum = 754; + pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; + pNSprite->shade = 8; + pNSprite->xrepeat = pTSprite->xrepeat; + pNSprite->yrepeat = pTSprite->yrepeat; + break; + } + case kViewEffectSmokeLow: + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - int top, bottom; - GetSpriteExtents(pTSprite, &top, &bottom); - pNSprite->pos.Z = bottom; - if (pTSprite->type >= kDudeBase && pTSprite->type < kDudeMax) - pNSprite->picnum = 672; - else - pNSprite->picnum = 754; - pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; - pNSprite->shade = 8; - pNSprite->xrepeat = pTSprite->xrepeat; - pNSprite->yrepeat = pTSprite->yrepeat; - break; - } - case kViewEffectTorchHigh: - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + int top, bottom; + GetSpriteExtents(pTSprite, &top, &bottom); + pNSprite->pos.Z = bottom; + if (pTSprite->type >= kDudeBase && pTSprite->type < kDudeMax) + pNSprite->picnum = 672; + else + pNSprite->picnum = 754; + pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; + pNSprite->shade = 8; + pNSprite->xrepeat = pTSprite->xrepeat; + pNSprite->yrepeat = pTSprite->yrepeat; + break; + } + case kViewEffectTorchHigh: + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - int top, bottom; - GetSpriteExtents(pTSprite, &top, &bottom); - pNSprite->pos.Z = top; - pNSprite->picnum = 2101; - pNSprite->shade = -128; - pNSprite->xrepeat = pNSprite->yrepeat = (tileWidth(pTSprite->picnum)*pTSprite->xrepeat)/32; - break; - } - case kViewEffectTorchLow: - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + int top, bottom; + GetSpriteExtents(pTSprite, &top, &bottom); + pNSprite->pos.Z = top; + pNSprite->picnum = 2101; + pNSprite->shade = -128; + pNSprite->xrepeat = pNSprite->yrepeat = (tileWidth(pTSprite->picnum) * pTSprite->xrepeat) / 32; + break; + } + case kViewEffectTorchLow: + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - int top, bottom; - GetSpriteExtents(pTSprite, &top, &bottom); - pNSprite->pos.Z = bottom; - pNSprite->picnum = 2101; - pNSprite->shade = -128; - pNSprite->xrepeat = pNSprite->yrepeat = (tileWidth(pTSprite->picnum)*pTSprite->xrepeat)/32; - break; - } - case kViewEffectShadow: - { - if (r_shadows) - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + int top, bottom; + GetSpriteExtents(pTSprite, &top, &bottom); + pNSprite->pos.Z = bottom; + pNSprite->picnum = 2101; + pNSprite->shade = -128; + pNSprite->xrepeat = pNSprite->yrepeat = (tileWidth(pTSprite->picnum) * pTSprite->xrepeat) / 32; + break; + } + case kViewEffectShadow: + { + if (r_shadows) + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - pNSprite->pos.Z = getflorzofslopeptr(pTSprite->sector(), pNSprite->pos.X, pNSprite->pos.Y); - pNSprite->shade = 127; - pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; - pNSprite->xrepeat = pTSprite->xrepeat; - pNSprite->yrepeat = pTSprite->yrepeat >> 2; - pNSprite->picnum = pTSprite->picnum; - pNSprite->pal = 5; - int height = tileHeight(pNSprite->picnum); - int center = height / 2 + tileTopOffset(pNSprite->picnum); - pNSprite->pos.Z -= (pNSprite->yrepeat << 2) * (height - center); - } - break; - } - case kViewEffectFlareHalo: - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + pNSprite->pos.Z = getflorzofslopeptr(pTSprite->sector(), pNSprite->pos.X, pNSprite->pos.Y); + pNSprite->shade = 127; + pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; + pNSprite->xrepeat = pTSprite->xrepeat; + pNSprite->yrepeat = pTSprite->yrepeat >> 2; + pNSprite->picnum = pTSprite->picnum; + pNSprite->pal = 5; + int height = tileHeight(pNSprite->picnum); + int center = height / 2 + tileTopOffset(pNSprite->picnum); + pNSprite->pos.Z -= (pNSprite->yrepeat << 2) * (height - center); + } + break; + } + case kViewEffectFlareHalo: + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - pNSprite->shade = -128; - pNSprite->pal = 2; - pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; - pNSprite->pos.Z = pTSprite->pos.Z; - pNSprite->xrepeat = pTSprite->xrepeat; - pNSprite->yrepeat = pTSprite->yrepeat; - pNSprite->picnum = 2427; - break; - } - case kViewEffectCeilGlow: - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + pNSprite->shade = -128; + pNSprite->pal = 2; + pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; + pNSprite->pos.Z = pTSprite->pos.Z; + pNSprite->xrepeat = pTSprite->xrepeat; + pNSprite->yrepeat = pTSprite->yrepeat; + pNSprite->picnum = 2427; + break; + } + case kViewEffectCeilGlow: + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - sectortype *pSector = pTSprite->sector(); - pNSprite->pos.X = pTSprite->pos.X; - pNSprite->pos.Y = pTSprite->pos.Y; - pNSprite->pos.Z = pSector->ceilingz; - pNSprite->picnum = 624; - pNSprite->shade = ((pTSprite->pos.Z-pSector->ceilingz)>>8)-64; - pNSprite->pal = 2; - pNSprite->xrepeat = pNSprite->yrepeat = 64; - pNSprite->cstat |= CSTAT_SPRITE_ONE_SIDE | CSTAT_SPRITE_ALIGNMENT_FLOOR | CSTAT_SPRITE_YFLIP | CSTAT_SPRITE_TRANSLUCENT; - pNSprite->ang = pTSprite->ang; - pNSprite->ownerActor = pTSprite->ownerActor; - break; - } - case kViewEffectFloorGlow: - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + sectortype* pSector = pTSprite->sector(); + pNSprite->pos.X = pTSprite->pos.X; + pNSprite->pos.Y = pTSprite->pos.Y; + pNSprite->pos.Z = pSector->ceilingz; + pNSprite->picnum = 624; + pNSprite->shade = ((pTSprite->pos.Z - pSector->ceilingz) >> 8) - 64; + pNSprite->pal = 2; + pNSprite->xrepeat = pNSprite->yrepeat = 64; + pNSprite->cstat |= CSTAT_SPRITE_ONE_SIDE | CSTAT_SPRITE_ALIGNMENT_FLOOR | CSTAT_SPRITE_YFLIP | CSTAT_SPRITE_TRANSLUCENT; + pNSprite->ang = pTSprite->ang; + pNSprite->ownerActor = pTSprite->ownerActor; + break; + } + case kViewEffectFloorGlow: + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - sectortype *pSector = pTSprite->sector(); - pNSprite->pos.X = pTSprite->pos.X; - pNSprite->pos.Y = pTSprite->pos.Y; - pNSprite->pos.Z = pSector->floorz; - pNSprite->picnum = 624; - uint8_t nShade = (pSector->floorz-pTSprite->pos.Z)>>8; - pNSprite->shade = nShade-32; - pNSprite->pal = 2; - pNSprite->xrepeat = pNSprite->yrepeat = nShade; - pNSprite->cstat |= CSTAT_SPRITE_ONE_SIDE | CSTAT_SPRITE_ALIGNMENT_FLOOR | CSTAT_SPRITE_TRANSLUCENT; - pNSprite->ang = pTSprite->ang; - pNSprite->ownerActor = pTSprite->ownerActor; - break; - } - case kViewEffectSpear: - { - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + sectortype* pSector = pTSprite->sector(); + pNSprite->pos.X = pTSprite->pos.X; + pNSprite->pos.Y = pTSprite->pos.Y; + pNSprite->pos.Z = pSector->floorz; + pNSprite->picnum = 624; + uint8_t nShade = (pSector->floorz - pTSprite->pos.Z) >> 8; + pNSprite->shade = nShade - 32; + pNSprite->pal = 2; + pNSprite->xrepeat = pNSprite->yrepeat = nShade; + pNSprite->cstat |= CSTAT_SPRITE_ONE_SIDE | CSTAT_SPRITE_ALIGNMENT_FLOOR | CSTAT_SPRITE_TRANSLUCENT; + pNSprite->ang = pTSprite->ang; + pNSprite->ownerActor = pTSprite->ownerActor; + break; + } + case kViewEffectSpear: + { + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - pNSprite->pos.Z = pTSprite->pos.Z; - if (gDetail > 1) - pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT | CSTAT_SPRITE_TRANS_FLIP; - pNSprite->shade = ClipLow(pTSprite->shade-32, -128); - pNSprite->xrepeat = pTSprite->xrepeat; - pNSprite->yrepeat = 64; - pNSprite->picnum = 775; - break; - } - case kViewEffectShowWeapon: - { - assert(pTSprite->type >= kDudePlayer1 && pTSprite->type <= kDudePlayer8); - PLAYER *pPlayer = &gPlayer[pTSprite->type-kDudePlayer1]; - WEAPONICON weaponIcon = gWeaponIcon[pPlayer->curWeapon]; - auto& nTile = weaponIcon.nTile; - if (nTile < 0) break; - auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); - if (!pNSprite) - break; + pNSprite->pos.Z = pTSprite->pos.Z; + if (gDetail > 1) + pNSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT | CSTAT_SPRITE_TRANS_FLIP; + pNSprite->shade = ClipLow(pTSprite->shade - 32, -128); + pNSprite->xrepeat = pTSprite->xrepeat; + pNSprite->yrepeat = 64; + pNSprite->picnum = 775; + break; + } + case kViewEffectShowWeapon: + { + assert(pTSprite->type >= kDudePlayer1 && pTSprite->type <= kDudePlayer8); + PLAYER* pPlayer = &gPlayer[pTSprite->type - kDudePlayer1]; + WEAPONICON weaponIcon = gWeaponIcon[pPlayer->curWeapon]; + auto& nTile = weaponIcon.nTile; + if (nTile < 0) break; + auto pNSprite = viewInsertTSprite(tsprite, spritesortcnt, pTSprite->sector(), 32767, pTSprite); + if (!pNSprite) + break; - pNSprite->pos.X = pTSprite->pos.X; - pNSprite->pos.Y = pTSprite->pos.Y; - pNSprite->pos.Z = pTSprite->pos.Z-(32<<8); - pNSprite->pos.Z -= weaponIcon.zOffset<<8; // offset up - pNSprite->picnum = nTile; - pNSprite->shade = pTSprite->shade; - pNSprite->xrepeat = 32; - pNSprite->yrepeat = 32; - auto& nVoxel = voxelIndex[nTile]; - if (cl_showweapon == 2 && r_voxels && nVoxel != -1) - { - pNSprite->ang = (gView->actor->spr.ang + 512) & 2047; // always face viewer - pNSprite->cstat |= CSTAT_SPRITE_ALIGNMENT_SLAB; - pNSprite->cstat &= ~CSTAT_SPRITE_YFLIP; - pNSprite->picnum = nVoxel; - if (pPlayer->curWeapon == kWeapLifeLeech) // position lifeleech behind player - { - pNSprite->pos.X += MulScale(128, Cos(gView->actor->spr.ang), 30); - pNSprite->pos.Y += MulScale(128, Sin(gView->actor->spr.ang), 30); - } - if ((pPlayer->curWeapon == kWeapLifeLeech) || (pPlayer->curWeapon == kWeapVoodooDoll)) // make lifeleech/voodoo doll always face viewer like sprite - pNSprite->ang = (pNSprite->ang + 512) & 2047; // offset angle 90 degrees - } - break; - } - } - return NULL; + pNSprite->pos.X = pTSprite->pos.X; + pNSprite->pos.Y = pTSprite->pos.Y; + pNSprite->pos.Z = pTSprite->pos.Z - (32 << 8); + pNSprite->pos.Z -= weaponIcon.zOffset << 8; // offset up + pNSprite->picnum = nTile; + pNSprite->shade = pTSprite->shade; + pNSprite->xrepeat = 32; + pNSprite->yrepeat = 32; + auto& nVoxel = voxelIndex[nTile]; + if (cl_showweapon == 2 && r_voxels && nVoxel != -1) + { + pNSprite->ang = (gView->actor->spr.ang + 512) & 2047; // always face viewer + pNSprite->cstat |= CSTAT_SPRITE_ALIGNMENT_SLAB; + pNSprite->cstat &= ~CSTAT_SPRITE_YFLIP; + pNSprite->picnum = nVoxel; + if (pPlayer->curWeapon == kWeapLifeLeech) // position lifeleech behind player + { + pNSprite->pos.X += MulScale(128, Cos(gView->actor->spr.ang), 30); + pNSprite->pos.Y += MulScale(128, Sin(gView->actor->spr.ang), 30); + } + if ((pPlayer->curWeapon == kWeapLifeLeech) || (pPlayer->curWeapon == kWeapVoodooDoll)) // make lifeleech/voodoo doll always face viewer like sprite + pNSprite->ang = (pNSprite->ang + 512) & 2047; // offset angle 90 degrees + } + break; + } + } + return NULL; } -static void viewApplyDefaultPal(tspritetype *pTSprite, sectortype const *pSector) +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void viewApplyDefaultPal(tspritetype* pTSprite, sectortype const* pSector) { - XSECTOR const *pXSector = pSector->hasX()? &pSector->xs() : nullptr; - if (pXSector && pXSector->color && (VanillaMode() || pSector->floorpal != 0)) - { - copyfloorpal(pTSprite, pSector); - } + XSECTOR const* pXSector = pSector->hasX() ? &pSector->xs() : nullptr; + if (pXSector && pXSector->color && (VanillaMode() || pSector->floorpal != 0)) + { + copyfloorpal(pTSprite, pSector); + } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void viewProcessSprites(tspritetype* tsprite, int& spritesortcnt, int32_t cX, int32_t cY, int32_t cZ, int32_t cA, int32_t smoothratio) { // shift before interpolating to increase precision. - int myclock = (PlayClock<<3) + MulScale(4<<3, smoothratio, 16); - assert(spritesortcnt <= MAXSPRITESONSCREEN); - gCameraAng = cA; - int nViewSprites = spritesortcnt; - for (int nTSprite = spritesortcnt-1; nTSprite >= 0; nTSprite--) - { - tspritetype *pTSprite = &tsprite[nTSprite]; - auto owneractor = static_cast(pTSprite->ownerActor); - if (owneractor->spr.detail > gDetail) - { - pTSprite->xrepeat = 0; - continue; - } - int nTile = pTSprite->picnum; - if (nTile < 0 || nTile >= kMaxTiles) - { - pTSprite->xrepeat = 0; - continue; - } - // skip picnum 0 on face sprites. picnum 0 is a simple wall texture in Blood, - // but there are maps that use 0 on some operator sprites that may show up in potals as a result. - // Since the wall texture is perfectly fine for wall and floor sprites, these will be allowed to pass. - if (nTile == 0 && (pTSprite->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) == CSTAT_SPRITE_ALIGNMENT_FACING) - { - pTSprite->xrepeat = 0; - continue; - } + int myclock = (PlayClock << 3) + MulScale(4 << 3, smoothratio, 16); + assert(spritesortcnt <= MAXSPRITESONSCREEN); + gCameraAng = cA; + int nViewSprites = spritesortcnt; + for (int nTSprite = spritesortcnt - 1; nTSprite >= 0; nTSprite--) + { + tspritetype* pTSprite = &tsprite[nTSprite]; + auto owneractor = static_cast(pTSprite->ownerActor); + if (owneractor->spr.detail > gDetail) + { + pTSprite->xrepeat = 0; + continue; + } + int nTile = pTSprite->picnum; + if (nTile < 0 || nTile >= kMaxTiles) + { + pTSprite->xrepeat = 0; + continue; + } + // skip picnum 0 on face sprites. picnum 0 is a simple wall texture in Blood, + // but there are maps that use 0 on some operator sprites that may show up in potals as a result. + // Since the wall texture is perfectly fine for wall and floor sprites, these will be allowed to pass. + if (nTile == 0 && (pTSprite->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) == CSTAT_SPRITE_ALIGNMENT_FACING) + { + pTSprite->xrepeat = 0; + continue; + } - if (cl_interpolate && owneractor->interpolated && !(pTSprite->flags&512)) - { - pTSprite->pos = pTSprite->interpolatedvec3(gInterpolate); - pTSprite->ang = pTSprite->interpolatedang(gInterpolate); - } - int nAnim = 0; - switch (picanm[nTile].extra & 7) { - case 0: - if (!owneractor->hasX()) break; - switch (pTSprite->type) { - case kSwitchToggle: - case kSwitchOneWay: - if (owneractor->xspr.state) nAnim = 1; - break; - case kSwitchCombo: - nAnim = owneractor->xspr.data1; - break; - } - break; - case 1: - { - if (tilehasmodelorvoxel(pTSprite->picnum, pTSprite->pal) && !(owneractor->sprext.flags&SPREXT_NOTMD)) - { - pTSprite->cstat &= ~CSTAT_SPRITE_XFLIP; - break; - } - int dX = cX - pTSprite->pos.X; - int dY = cY - pTSprite->pos.Y; - RotateVector(&dX, &dY, 128-pTSprite->ang); - nAnim = GetOctant(dX, dY); - if (nAnim <= 4) - { - pTSprite->cstat &= ~CSTAT_SPRITE_XFLIP; - } - else - { - nAnim = 8 - nAnim; - pTSprite->cstat |= CSTAT_SPRITE_XFLIP; - } - break; - } - case 2: - { - if (tilehasmodelorvoxel(pTSprite->picnum, pTSprite->pal) && !(owneractor->sprext.flags&SPREXT_NOTMD)) - { - pTSprite->cstat &= ~CSTAT_SPRITE_XFLIP; - break; - } - int dX = cX - pTSprite->pos.X; - int dY = cY - pTSprite->pos.Y; - RotateVector(&dX, &dY, 128-pTSprite->ang); - nAnim = GetOctant(dX, dY); - break; - } - case 3: - { - if (owneractor->hasX()) - { - if (owneractor->hit.florhit.type == kHitNone) - nAnim = 1; - } - else - { - int top, bottom; - GetSpriteExtents(pTSprite, &top, &bottom); - if (getflorzofslopeptr(pTSprite->sector(), pTSprite->pos.X, pTSprite->pos.Y) > bottom) - nAnim = 1; - } - break; - } - case 6: - case 7: - { - if (hw_models && md_tilehasmodel(pTSprite->picnum, pTSprite->pal) >= 0 && !(owneractor->sprext.flags&SPREXT_NOTMD)) - break; + if (cl_interpolate && owneractor->interpolated && !(pTSprite->flags & 512)) + { + pTSprite->pos = pTSprite->interpolatedvec3(gInterpolate); + pTSprite->ang = pTSprite->interpolatedang(gInterpolate); + } + int nAnim = 0; + switch (picanm[nTile].extra & 7) { + case 0: + if (!owneractor->hasX()) break; + switch (pTSprite->type) { + case kSwitchToggle: + case kSwitchOneWay: + if (owneractor->xspr.state) nAnim = 1; + break; + case kSwitchCombo: + nAnim = owneractor->xspr.data1; + break; + } + break; + case 1: + { + if (tilehasmodelorvoxel(pTSprite->picnum, pTSprite->pal) && !(owneractor->sprext.flags & SPREXT_NOTMD)) + { + pTSprite->cstat &= ~CSTAT_SPRITE_XFLIP; + break; + } + int dX = cX - pTSprite->pos.X; + int dY = cY - pTSprite->pos.Y; + RotateVector(&dX, &dY, 128 - pTSprite->ang); + nAnim = GetOctant(dX, dY); + if (nAnim <= 4) + { + pTSprite->cstat &= ~CSTAT_SPRITE_XFLIP; + } + else + { + nAnim = 8 - nAnim; + pTSprite->cstat |= CSTAT_SPRITE_XFLIP; + } + break; + } + case 2: + { + if (tilehasmodelorvoxel(pTSprite->picnum, pTSprite->pal) && !(owneractor->sprext.flags & SPREXT_NOTMD)) + { + pTSprite->cstat &= ~CSTAT_SPRITE_XFLIP; + break; + } + int dX = cX - pTSprite->pos.X; + int dY = cY - pTSprite->pos.Y; + RotateVector(&dX, &dY, 128 - pTSprite->ang); + nAnim = GetOctant(dX, dY); + break; + } + case 3: + { + if (owneractor->hasX()) + { + if (owneractor->hit.florhit.type == kHitNone) + nAnim = 1; + } + else + { + int top, bottom; + GetSpriteExtents(pTSprite, &top, &bottom); + if (getflorzofslopeptr(pTSprite->sector(), pTSprite->pos.X, pTSprite->pos.Y) > bottom) + nAnim = 1; + } + break; + } + case 6: + case 7: + { + if (hw_models && md_tilehasmodel(pTSprite->picnum, pTSprite->pal) >= 0 && !(owneractor->sprext.flags & SPREXT_NOTMD)) + break; - // Can be overridden by def script - if (r_voxels && tiletovox[pTSprite->picnum] == -1 && voxelIndex[pTSprite->picnum] != -1 && !(owneractor->sprext.flags&SPREXT_NOTMD)) - { - if ((pTSprite->flags&kHitagRespawn) == 0) - { - pTSprite->cstat |= CSTAT_SPRITE_ALIGNMENT_SLAB; - pTSprite->cstat &= ~(CSTAT_SPRITE_XFLIP | CSTAT_SPRITE_YFLIP); - pTSprite->yoffset += tileTopOffset(pTSprite->picnum); - pTSprite->picnum = voxelIndex[pTSprite->picnum]; - if ((picanm[nTile].extra&7) == 7) - { - pTSprite->ang = myclock & 2047; - } - } - } - break; - } - } - while (nAnim > 0) - { - pTSprite->picnum += picanm[pTSprite->picnum].num+1; - nAnim--; - } + // Can be overridden by def script + if (r_voxels && tiletovox[pTSprite->picnum] == -1 && voxelIndex[pTSprite->picnum] != -1 && !(owneractor->sprext.flags & SPREXT_NOTMD)) + { + if ((pTSprite->flags & kHitagRespawn) == 0) + { + pTSprite->cstat |= CSTAT_SPRITE_ALIGNMENT_SLAB; + pTSprite->cstat &= ~(CSTAT_SPRITE_XFLIP | CSTAT_SPRITE_YFLIP); + pTSprite->yoffset += tileTopOffset(pTSprite->picnum); + pTSprite->picnum = voxelIndex[pTSprite->picnum]; + if ((picanm[nTile].extra & 7) == 7) + { + pTSprite->ang = myclock & 2047; + } + } + } + break; + } + } + while (nAnim > 0) + { + pTSprite->picnum += picanm[pTSprite->picnum].num + 1; + nAnim--; + } - if ((pTSprite->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) != CSTAT_SPRITE_ALIGNMENT_SLAB && r_voxels && !(owneractor->sprext.flags&SPREXT_NOTMD)) - { - int const nRootTile = pTSprite->picnum; - int nAnimTile = pTSprite->picnum + qanimateoffs(pTSprite->picnum, 32768 + (pTSprite->ownerActor->GetIndex() & 16383)); + if ((pTSprite->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) != CSTAT_SPRITE_ALIGNMENT_SLAB && r_voxels && !(owneractor->sprext.flags & SPREXT_NOTMD)) + { + int const nRootTile = pTSprite->picnum; + int nAnimTile = pTSprite->picnum + qanimateoffs(pTSprite->picnum, 32768 + (pTSprite->ownerActor->GetIndex() & 16383)); #if 0 - if (tiletovox[nAnimTile] != -1) - { - pTSprite->yoffset += tileTopOffset(nAnimTile); - pTSprite->xoffset += tileLeftOffset(nAnimTile); - } + if (tiletovox[nAnimTile] != -1) + { + pTSprite->yoffset += tileTopOffset(nAnimTile); + pTSprite->xoffset += tileLeftOffset(nAnimTile); + } #endif - int const nVoxel = tiletovox[pTSprite->picnum]; + int const nVoxel = tiletovox[pTSprite->picnum]; - if (nVoxel != -1 && (picanm[nRootTile].extra & 7) == 7) - pTSprite->cstat2 |= CSTAT2_SPRITE_MDLROTATE; // per-sprite rotation setting. - } + if (nVoxel != -1 && (picanm[nRootTile].extra & 7) == 7) + pTSprite->cstat2 |= CSTAT2_SPRITE_MDLROTATE; // per-sprite rotation setting. + } - if ((pTSprite->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) != CSTAT_SPRITE_ALIGNMENT_SLAB && hw_models && !(owneractor->sprext.flags&SPREXT_NOTMD)) - { - int const nRootTile = pTSprite->picnum; - int nAnimTile = pTSprite->picnum + qanimateoffs(pTSprite->picnum, 32768 + (pTSprite->ownerActor->GetIndex() & 16383)); + if ((pTSprite->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) != CSTAT_SPRITE_ALIGNMENT_SLAB && hw_models && !(owneractor->sprext.flags & SPREXT_NOTMD)) + { + int const nRootTile = pTSprite->picnum; + int nAnimTile = pTSprite->picnum + qanimateoffs(pTSprite->picnum, 32768 + (pTSprite->ownerActor->GetIndex() & 16383)); - if (tile2model[Ptile2tile(nAnimTile, pTSprite->pal)].modelid >= 0 && - tile2model[Ptile2tile(nAnimTile, pTSprite->pal)].framenum >= 0) - { - pTSprite->yoffset += tileTopOffset(nAnimTile); - pTSprite->xoffset += tileLeftOffset(nAnimTile); + if (tile2model[Ptile2tile(nAnimTile, pTSprite->pal)].modelid >= 0 && + tile2model[Ptile2tile(nAnimTile, pTSprite->pal)].framenum >= 0) + { + pTSprite->yoffset += tileTopOffset(nAnimTile); + pTSprite->xoffset += tileLeftOffset(nAnimTile); - if ((picanm[nRootTile].extra&7) == 7) - pTSprite->cstat2 |= CSTAT2_SPRITE_MDLROTATE; // per-sprite rotation setting. - } - } + if ((picanm[nRootTile].extra & 7) == 7) + pTSprite->cstat2 |= CSTAT2_SPRITE_MDLROTATE; // per-sprite rotation setting. + } + } - sectortype *pSector = pTSprite->sector(); - XSECTOR const* pXSector = pSector->hasX() ? &pSector->xs() : nullptr; - int nShade = pTSprite->shade; + sectortype* pSector = pTSprite->sector(); + XSECTOR const* pXSector = pSector->hasX() ? &pSector->xs() : nullptr; + int nShade = pTSprite->shade; - if ((pSector->ceilingstat & CSTAT_SECTOR_SKY) && (pSector->floorstat & CSTAT_SECTOR_NO_CEILINGSHADE) == 0) - { - nShade += tileShade[pSector->ceilingpicnum]+pSector->ceilingshade; - } - else - { - nShade += tileShade[pSector->floorpicnum]+pSector->floorshade; - } - nShade += tileShade[pTSprite->picnum]; - pTSprite->shade = ClipRange(nShade, -128, 127); - if ((pTSprite->flags&kHitagRespawn) && pTSprite->ownerActor->spr.owner == 3 && owneractor->hasX()) // Where does this 3 come from? Nothing sets it. - { - pTSprite->xrepeat = 48; - pTSprite->yrepeat = 48; - pTSprite->shade = -128; - pTSprite->picnum = 2272 + 2* owneractor->xspr.respawnPending; - pTSprite->cstat &= ~(CSTAT_SPRITE_TRANSLUCENT | CSTAT_SPRITE_TRANS_FLIP); - if (((IsItemSprite(pTSprite) || IsAmmoSprite(pTSprite)) && gGameOptions.nItemSettings == 2) - || (IsWeaponSprite(pTSprite) && gGameOptions.nWeaponSettings == 3)) - { - pTSprite->xrepeat = pTSprite->yrepeat = 48; - } - else - { - pTSprite->xrepeat = pTSprite->yrepeat = 0; - } - } - if (spritesortcnt >= MAXSPRITESONSCREEN) continue; - if (owneractor->hasX() && owneractor->xspr.burnTime > 0) - { - pTSprite->shade = ClipRange(pTSprite->shade-16-QRandom(8), -128, 127); - } - if (pTSprite->flags&256) - { - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectSmokeHigh); - } - if (pTSprite->flags&1024) - { - pTSprite->cstat |= CSTAT_SPRITE_XFLIP; - } - if (pTSprite->flags&2048) - { - pTSprite->cstat |= CSTAT_SPRITE_YFLIP; - } - switch (pTSprite->statnum) { - case kStatDecoration: { - switch (pTSprite->type) { - case kDecorationCandle: - if (!owneractor->hasX() || owneractor->xspr.state == 1) { - pTSprite->shade = -128; - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectPhase); - } else { - pTSprite->shade = -8; - } - break; - case kDecorationTorch: - if (!owneractor->hasX() || owneractor->xspr.state == 1) { - pTSprite->picnum++; - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectTorchHigh); - } else { - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectSmokeHigh); - } - break; - default: - viewApplyDefaultPal(pTSprite, pSector); - break; - } - } - break; - case kStatItem: { - switch (pTSprite->type) { - case kItemFlagABase: - if (owneractor->hasX() && owneractor->xspr.state > 0 && gGameOptions.nGameType == 3) { - auto pNTSprite = viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectBigFlag); - if (pNTSprite) pNTSprite->pal = 10; - } - break; - case kItemFlagBBase: - if (owneractor->hasX() && owneractor->xspr.state > 0 && gGameOptions.nGameType == 3) { - auto pNTSprite = viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectBigFlag); - if (pNTSprite) pNTSprite->pal = 7; - } - break; - case kItemFlagA: - pTSprite->pal = 10; - pTSprite->cstat |= CSTAT_SPRITE_BLOOD_BIT2; - break; - case kItemFlagB: - pTSprite->pal = 7; - pTSprite->cstat |= CSTAT_SPRITE_BLOOD_BIT2; - break; - default: - if (pTSprite->type >= kItemKeySkull && pTSprite->type < kItemKeyMax) - pTSprite->shade = -128; + if ((pSector->ceilingstat & CSTAT_SECTOR_SKY) && (pSector->floorstat & CSTAT_SECTOR_NO_CEILINGSHADE) == 0) + { + nShade += tileShade[pSector->ceilingpicnum] + pSector->ceilingshade; + } + else + { + nShade += tileShade[pSector->floorpicnum] + pSector->floorshade; + } + nShade += tileShade[pTSprite->picnum]; + pTSprite->shade = ClipRange(nShade, -128, 127); + if ((pTSprite->flags & kHitagRespawn) && pTSprite->ownerActor->spr.owner == 3 && owneractor->hasX()) // Where does this 3 come from? Nothing sets it. + { + pTSprite->xrepeat = 48; + pTSprite->yrepeat = 48; + pTSprite->shade = -128; + pTSprite->picnum = 2272 + 2 * owneractor->xspr.respawnPending; + pTSprite->cstat &= ~(CSTAT_SPRITE_TRANSLUCENT | CSTAT_SPRITE_TRANS_FLIP); + if (((IsItemSprite(pTSprite) || IsAmmoSprite(pTSprite)) && gGameOptions.nItemSettings == 2) + || (IsWeaponSprite(pTSprite) && gGameOptions.nWeaponSettings == 3)) + { + pTSprite->xrepeat = pTSprite->yrepeat = 48; + } + else + { + pTSprite->xrepeat = pTSprite->yrepeat = 0; + } + } + if (spritesortcnt >= MAXSPRITESONSCREEN) continue; + if (owneractor->hasX() && owneractor->xspr.burnTime > 0) + { + pTSprite->shade = ClipRange(pTSprite->shade - 16 - QRandom(8), -128, 127); + } + if (pTSprite->flags & 256) + { + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectSmokeHigh); + } + if (pTSprite->flags & 1024) + { + pTSprite->cstat |= CSTAT_SPRITE_XFLIP; + } + if (pTSprite->flags & 2048) + { + pTSprite->cstat |= CSTAT_SPRITE_YFLIP; + } + switch (pTSprite->statnum) { + case kStatDecoration: { + switch (pTSprite->type) { + case kDecorationCandle: + if (!owneractor->hasX() || owneractor->xspr.state == 1) { + pTSprite->shade = -128; + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectPhase); + } + else { + pTSprite->shade = -8; + } + break; + case kDecorationTorch: + if (!owneractor->hasX() || owneractor->xspr.state == 1) { + pTSprite->picnum++; + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectTorchHigh); + } + else { + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectSmokeHigh); + } + break; + default: + viewApplyDefaultPal(pTSprite, pSector); + break; + } + } + break; + case kStatItem: { + switch (pTSprite->type) { + case kItemFlagABase: + if (owneractor->hasX() && owneractor->xspr.state > 0 && gGameOptions.nGameType == 3) { + auto pNTSprite = viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectBigFlag); + if (pNTSprite) pNTSprite->pal = 10; + } + break; + case kItemFlagBBase: + if (owneractor->hasX() && owneractor->xspr.state > 0 && gGameOptions.nGameType == 3) { + auto pNTSprite = viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectBigFlag); + if (pNTSprite) pNTSprite->pal = 7; + } + break; + case kItemFlagA: + pTSprite->pal = 10; + pTSprite->cstat |= CSTAT_SPRITE_BLOOD_BIT2; + break; + case kItemFlagB: + pTSprite->pal = 7; + pTSprite->cstat |= CSTAT_SPRITE_BLOOD_BIT2; + break; + default: + if (pTSprite->type >= kItemKeySkull && pTSprite->type < kItemKeyMax) + pTSprite->shade = -128; - viewApplyDefaultPal(pTSprite, pSector); - break; - } - } - break; - case kStatProjectile: { - switch (pTSprite->type) { - case kMissileTeslaAlt: - pTSprite->yrepeat = 128; - pTSprite->cstat |= CSTAT_SPRITE_ALIGNMENT_FLOOR; - break; - case kMissileTeslaRegular: - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectTesla); - break; - case kMissileButcherKnife: - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectTrail); - break; - case kMissileFlareRegular: - case kMissileFlareAlt: - if (pTSprite->statnum == kStatFlare) { - if (owneractor->GetTarget() == gView->actor) - { - pTSprite->xrepeat = 0; - break; - } - } - - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectFlareHalo); - if (pTSprite->type != kMissileFlareRegular) break; - sectortype *pSector1 = pTSprite->sector(); - - int zDiff = (pTSprite->pos.Z - pSector1->ceilingz) >> 8; - if ((pSector1->ceilingstat & CSTAT_SECTOR_SKY) == 0 && zDiff < 64) { - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectCeilGlow); - } - - zDiff = (pSector1->floorz - pTSprite->pos.Z) >> 8; - if ((pSector1->floorstat & CSTAT_SECTOR_SKY) == 0 && zDiff < 64) { - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectFloorGlow); - } - break; - } - break; - } - case kStatDude: - { - if (pTSprite->type == kDudeHand && owneractor->hasX() && owneractor->xspr.aiState == &hand13A3B4) - { - auto target = owneractor->GetTarget(); - if (target && target->IsPlayerActor()) - { - pTSprite->xrepeat = 0; - break; - } - } - - if (pXSector && pXSector->color) copyfloorpal(pTSprite, pSector); - if (powerupCheck(gView, kPwUpBeastVision) > 0) pTSprite->shade = -128; + viewApplyDefaultPal(pTSprite, pSector); + break; + } + } + break; + case kStatProjectile: { + switch (pTSprite->type) { + case kMissileTeslaAlt: + pTSprite->yrepeat = 128; + pTSprite->cstat |= CSTAT_SPRITE_ALIGNMENT_FLOOR; + break; + case kMissileTeslaRegular: + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectTesla); + break; + case kMissileButcherKnife: + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectTrail); + break; + case kMissileFlareRegular: + case kMissileFlareAlt: + if (pTSprite->statnum == kStatFlare) { + if (owneractor->GetTarget() == gView->actor) + { + pTSprite->xrepeat = 0; + break; + } + } - if (IsPlayerSprite(pTSprite)) { - PLAYER *pPlayer = &gPlayer[pTSprite->type-kDudePlayer1]; - if (powerupCheck(pPlayer, kPwUpShadowCloak) && !powerupCheck(gView, kPwUpBeastVision)) { - pTSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; - pTSprite->pal = 5; - } else if (powerupCheck(pPlayer, kPwUpDeathMask)) { - pTSprite->shade = -128; - pTSprite->pal = 5; - } else if (powerupCheck(pPlayer, kPwUpDoppleganger)) { - pTSprite->pal = 11+(gView->teamId&3); - } - - if (powerupCheck(pPlayer, kPwUpReflectShots)) { - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectReflectiveBall); - } - - if (cl_showweapon && gGameOptions.nGameType > 0 && gView) { - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectShowWeapon); - } - - if (pPlayer->flashEffect && (gView != pPlayer || gViewPos != VIEWPOS_0)) { - auto pNTSprite = viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectShoot); - if (pNTSprite) { - POSTURE *pPosture = &pPlayer->pPosture[pPlayer->lifeMode][pPlayer->posture]; - pNTSprite->pos.X += MulScale(pPosture->zOffset, Cos(pTSprite->ang), 28); - pNTSprite->pos.Y += MulScale(pPosture->zOffset, Sin(pTSprite->ang), 28); - pNTSprite->pos.Z = pPlayer->actor->spr.pos.Z-pPosture->xOffset; - } - } - - if (pPlayer->hasFlag > 0 && gGameOptions.nGameType == 3) { - if (pPlayer->hasFlag&1) { - auto pNTSprite = viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectFlag); - if (pNTSprite) - { - pNTSprite->pal = 10; - pNTSprite->cstat |= CSTAT_SPRITE_XFLIP; - } - } - if (pPlayer->hasFlag&2) { - auto pNTSprite = viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectFlag); - if (pNTSprite) - { - pNTSprite->pal = 7; - pNTSprite->cstat |= CSTAT_SPRITE_XFLIP; - } - } - } - } - - if (pTSprite->ownerActor != gView->actor || gViewPos != VIEWPOS_0) { - if (getflorzofslopeptr(pTSprite->sector(), pTSprite->pos.X, pTSprite->pos.Y) >= cZ) - { - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectShadow); - } - } + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectFlareHalo); + if (pTSprite->type != kMissileFlareRegular) break; + sectortype* pSector1 = pTSprite->sector(); - if (gModernMap && owneractor->hasX()) { // add target spot indicator for patrol dudes - if (owneractor->xspr.dudeFlag4 && aiInPatrolState(owneractor->xspr.aiState) && owneractor->xspr.data3 > 0 && owneractor->xspr.data3 <= kMaxPatrolSpotValue) - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectSpotProgress); - } - break; - } - case kStatTraps: { - if (pTSprite->type == kTrapSawCircular) { - if (owneractor->xspr.state) { - if (owneractor->xspr.data1) { - pTSprite->picnum = 772; - if (owneractor->xspr.data2) - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectSpear); - } - } - else if (owneractor->xspr.data1) pTSprite->picnum = 773; - else pTSprite->picnum = 656; - - } - break; - } - case kStatThing: { - viewApplyDefaultPal(pTSprite, pSector); + int zDiff = (pTSprite->pos.Z - pSector1->ceilingz) >> 8; + if ((pSector1->ceilingstat & CSTAT_SECTOR_SKY) == 0 && zDiff < 64) { + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectCeilGlow); + } - if (pTSprite->type < kThingBase || pTSprite->type >= kThingMax || owneractor->hit.florhit.type == kHitNone) - { - if ((pTSprite->flags & kPhysMove) && getflorzofslopeptr(pTSprite->sector(), pTSprite->pos.X, pTSprite->pos.Y) >= cZ) - viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectShadow); - } - } - break; - } - } + zDiff = (pSector1->floorz - pTSprite->pos.Z) >> 8; + if ((pSector1->floorstat & CSTAT_SECTOR_SKY) == 0 && zDiff < 64) { + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectFloorGlow); + } + break; + } + break; + } + case kStatDude: + { + if (pTSprite->type == kDudeHand && owneractor->hasX() && owneractor->xspr.aiState == &hand13A3B4) + { + auto target = owneractor->GetTarget(); + if (target && target->IsPlayerActor()) + { + pTSprite->xrepeat = 0; + break; + } + } - for (int nTSprite = spritesortcnt-1; nTSprite >= nViewSprites; nTSprite--) - { - tspritetype *pTSprite = &tsprite[nTSprite]; - int nAnim = 0; - switch (picanm[pTSprite->picnum].extra&7) - { - case 1: - { - int dX = cX - pTSprite->pos.X; - int dY = cY - pTSprite->pos.Y; - RotateVector(&dX, &dY, 128-pTSprite->ang); - nAnim = GetOctant(dX, dY); - if (nAnim <= 4) - { - pTSprite->cstat &= ~CSTAT_SPRITE_XFLIP; - } - else - { - nAnim = 8 - nAnim; - pTSprite->cstat |= CSTAT_SPRITE_XFLIP; - } - break; - } - case 2: - { - int dX = cX - pTSprite->pos.X; - int dY = cY - pTSprite->pos.Y; - RotateVector(&dX, &dY, 128-pTSprite->ang); - nAnim = GetOctant(dX, dY); - break; - } - } - while (nAnim > 0) - { - pTSprite->picnum += picanm[pTSprite->picnum].num+1; - nAnim--; - } - } + if (pXSector && pXSector->color) copyfloorpal(pTSprite, pSector); + if (powerupCheck(gView, kPwUpBeastVision) > 0) pTSprite->shade = -128; + + if (IsPlayerSprite(pTSprite)) { + PLAYER* pPlayer = &gPlayer[pTSprite->type - kDudePlayer1]; + if (powerupCheck(pPlayer, kPwUpShadowCloak) && !powerupCheck(gView, kPwUpBeastVision)) { + pTSprite->cstat |= CSTAT_SPRITE_TRANSLUCENT; + pTSprite->pal = 5; + } + else if (powerupCheck(pPlayer, kPwUpDeathMask)) { + pTSprite->shade = -128; + pTSprite->pal = 5; + } + else if (powerupCheck(pPlayer, kPwUpDoppleganger)) { + pTSprite->pal = 11 + (gView->teamId & 3); + } + + if (powerupCheck(pPlayer, kPwUpReflectShots)) { + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectReflectiveBall); + } + + if (cl_showweapon && gGameOptions.nGameType > 0 && gView) { + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectShowWeapon); + } + + if (pPlayer->flashEffect && (gView != pPlayer || gViewPos != VIEWPOS_0)) { + auto pNTSprite = viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectShoot); + if (pNTSprite) { + POSTURE* pPosture = &pPlayer->pPosture[pPlayer->lifeMode][pPlayer->posture]; + pNTSprite->pos.X += MulScale(pPosture->zOffset, Cos(pTSprite->ang), 28); + pNTSprite->pos.Y += MulScale(pPosture->zOffset, Sin(pTSprite->ang), 28); + pNTSprite->pos.Z = pPlayer->actor->spr.pos.Z - pPosture->xOffset; + } + } + + if (pPlayer->hasFlag > 0 && gGameOptions.nGameType == 3) { + if (pPlayer->hasFlag & 1) { + auto pNTSprite = viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectFlag); + if (pNTSprite) + { + pNTSprite->pal = 10; + pNTSprite->cstat |= CSTAT_SPRITE_XFLIP; + } + } + if (pPlayer->hasFlag & 2) { + auto pNTSprite = viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectFlag); + if (pNTSprite) + { + pNTSprite->pal = 7; + pNTSprite->cstat |= CSTAT_SPRITE_XFLIP; + } + } + } + } + + if (pTSprite->ownerActor != gView->actor || gViewPos != VIEWPOS_0) { + if (getflorzofslopeptr(pTSprite->sector(), pTSprite->pos.X, pTSprite->pos.Y) >= cZ) + { + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectShadow); + } + } + + if (gModernMap && owneractor->hasX()) { // add target spot indicator for patrol dudes + if (owneractor->xspr.dudeFlag4 && aiInPatrolState(owneractor->xspr.aiState) && owneractor->xspr.data3 > 0 && owneractor->xspr.data3 <= kMaxPatrolSpotValue) + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectSpotProgress); + } + break; + } + case kStatTraps: { + if (pTSprite->type == kTrapSawCircular) { + if (owneractor->xspr.state) { + if (owneractor->xspr.data1) { + pTSprite->picnum = 772; + if (owneractor->xspr.data2) + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectSpear); + } + } + else if (owneractor->xspr.data1) pTSprite->picnum = 773; + else pTSprite->picnum = 656; + + } + break; + } + case kStatThing: { + viewApplyDefaultPal(pTSprite, pSector); + + if (pTSprite->type < kThingBase || pTSprite->type >= kThingMax || owneractor->hit.florhit.type == kHitNone) + { + if ((pTSprite->flags & kPhysMove) && getflorzofslopeptr(pTSprite->sector(), pTSprite->pos.X, pTSprite->pos.Y) >= cZ) + viewAddEffect(tsprite, spritesortcnt, nTSprite, kViewEffectShadow); + } + } + break; + } + } + + for (int nTSprite = spritesortcnt - 1; nTSprite >= nViewSprites; nTSprite--) + { + tspritetype* pTSprite = &tsprite[nTSprite]; + int nAnim = 0; + switch (picanm[pTSprite->picnum].extra & 7) + { + case 1: + { + int dX = cX - pTSprite->pos.X; + int dY = cY - pTSprite->pos.Y; + RotateVector(&dX, &dY, 128 - pTSprite->ang); + nAnim = GetOctant(dX, dY); + if (nAnim <= 4) + { + pTSprite->cstat &= ~CSTAT_SPRITE_XFLIP; + } + else + { + nAnim = 8 - nAnim; + pTSprite->cstat |= CSTAT_SPRITE_XFLIP; + } + break; + } + case 2: + { + int dX = cX - pTSprite->pos.X; + int dY = cY - pTSprite->pos.Y; + RotateVector(&dX, &dY, 128 - pTSprite->ang); + nAnim = GetOctant(dX, dY); + break; + } + } + while (nAnim > 0) + { + pTSprite->picnum += picanm[pTSprite->picnum].num + 1; + nAnim--; + } + } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void GameInterface::processSprites(tspritetype* tsprite, int& spritesortcnt, int viewx, int viewy, int viewz, binangle viewang, double smoothRatio) { - viewProcessSprites(tsprite, spritesortcnt, viewx, viewy, viewz, viewang.asbuild(), int(smoothRatio)); + viewProcessSprites(tsprite, spritesortcnt, viewx, viewy, viewz, viewang.asbuild(), int(smoothRatio)); } int display_mirror; void GameInterface::EnterPortal(DCoreActor* viewer, int type) { - if (type == PORTAL_WALL_MIRROR) - { - display_mirror++; - if (viewer) viewer->spr.cstat &= ~CSTAT_SPRITE_INVISIBLE; - } + if (type == PORTAL_WALL_MIRROR) + { + display_mirror++; + if (viewer) viewer->spr.cstat &= ~CSTAT_SPRITE_INVISIBLE; + } } void GameInterface::LeavePortal(DCoreActor* viewer, int type) { - if (type == PORTAL_WALL_MIRROR) - { - display_mirror--; - if (viewer && display_mirror == 0 && !(viewer->spr.cstat & CSTAT_SPRITE_TRANSLUCENT)) viewer->spr.cstat |= CSTAT_SPRITE_INVISIBLE; - } + if (type == PORTAL_WALL_MIRROR) + { + display_mirror--; + if (viewer && display_mirror == 0 && !(viewer->spr.cstat & CSTAT_SPRITE_TRANSLUCENT)) viewer->spr.cstat |= CSTAT_SPRITE_INVISIBLE; + } } END_BLD_NS diff --git a/source/games/blood/src/asound.cpp b/source/games/blood/src/asound.cpp index 3b0b7ee3d..5533ab86e 100644 --- a/source/games/blood/src/asound.cpp +++ b/source/games/blood/src/asound.cpp @@ -41,6 +41,12 @@ struct AMB_CHANNEL AMB_CHANNEL ambChannels[kMaxAmbChannel]; int nAmbChannels = 0; +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void ambProcess(void) { if (!SoundEnabled()) @@ -90,6 +96,12 @@ void ambProcess(void) } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void ambKillAll(void) { AMB_CHANNEL *pChannel = ambChannels; @@ -101,6 +113,12 @@ void ambKillAll(void) nAmbChannels = 0; } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void ambInit(void) { ambKillAll(); diff --git a/source/games/blood/src/barf.cpp b/source/games/blood/src/barf.cpp index 2dfd1ce4d..057044ee7 100644 --- a/source/games/blood/src/barf.cpp +++ b/source/games/blood/src/barf.cpp @@ -135,6 +135,12 @@ void AddCmdDefine(char *text, int value) nCmdDefines++; } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + static void SplitPath(const char *pzPath, char *pzDirectory, char *pzFile, char *pzType) { int const nLength = (int)strlen(pzPath); @@ -180,6 +186,12 @@ static void SplitPath(const char *pzPath, char *pzDirectory, char *pzFile, char +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + // 174 bytes struct RFS { @@ -207,6 +219,12 @@ public: void UnsetMark(); }; +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + int RFS::Open(int lumpnum) { auto hFile = fileSystem.OpenFileReader(lumpnum); @@ -238,6 +256,12 @@ void RFS::Close() { } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void RFS::Increment() { if (_curChar == '\n') { @@ -254,6 +278,12 @@ void RFS::Increment() } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void RFS::SkipBeyondValue(char nVal) { while (_curChar && _curChar != nVal) { @@ -276,6 +306,12 @@ void RFS::UnsetMark() _curLine = _unknown7; } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void RFS::ScriptError(const char *message) { // TODO @@ -307,6 +343,12 @@ void RFS::ScriptError(const char *message) Printf("Error in %s line %d: %s\n\n%s", _fileName, _curLine, message, msg.Data()); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + uint8_t RFS::GetNextTag() { // skip any space characters @@ -493,6 +535,12 @@ uint8_t RFS::GetNextTag() // qAssert(1==0); // TODO - what to return here } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void ParseScript(int lumpnum) { char text[256]; @@ -933,6 +981,12 @@ void ParseScript(int lumpnum) rfs.Close(); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void addMemoryResource(char* filePath, char flags, int ID) { char zDirectory[BMAX_PATH]; @@ -945,6 +999,12 @@ void addMemoryResource(char* filePath, char flags, int ID) } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void ReadAllRFS() { bool found = false; diff --git a/source/games/blood/src/blood.cpp b/source/games/blood/src/blood.cpp index 1f9d84bfe..243dc3af1 100644 --- a/source/games/blood/src/blood.cpp +++ b/source/games/blood/src/blood.cpp @@ -71,6 +71,12 @@ IMPLEMENT_POINTER(xspr.burnSource) IMPLEMENT_POINTER(xspr.target) IMPLEMENT_POINTERS_END +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + size_t DBloodActor::PropagateMark() { condition[0].Mark(); @@ -109,6 +115,12 @@ int16_t startang; sectortype* startsector; +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void QuitGame(void) { throw CExitEvent(0); @@ -124,6 +136,12 @@ void EndLevel(void) seqKillAll(); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + TArray SpawnActors(BloodSpawnSpriteDef& sprites) { TArray spawns(sprites.sprites.Size(), true); @@ -153,6 +171,12 @@ TArray SpawnActors(BloodSpawnSpriteDef& sprites) return spawns; } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void PropagateMarkerReferences(void) { BloodStatIterator it(kStatMarker); @@ -194,6 +218,12 @@ void PropagateMarkerReferences(void) } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void StartLevel(MapRecord* level, bool newgame) { if (!level) return; @@ -329,6 +359,12 @@ void StartLevel(MapRecord* level, bool newgame) } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void NewLevel(MapRecord *sng, int skill, bool newgame) { if (skill != -1) gGameOptions.nDifficulty = skill; @@ -355,6 +391,12 @@ int GameInterface::GetCurrentSkill() } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void GameInterface::Ticker() { for (int i = connecthead; i >= 0; i = connectpoint2[i]) @@ -436,6 +478,12 @@ void GameInterface::Ticker() else r_NoInterpolate = true; } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void GameInterface::DrawBackground() { twod->ClearScreen(); @@ -461,6 +509,12 @@ static void SetTileNames() void ReadAllRFS(); +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void GameInterface::loadPalette(void) { // in nearly typical Blood fashion it had to use an inverse of the original translucency settings... @@ -529,6 +583,12 @@ void GameInterface::loadPalette(void) paletteloaded = PALETTE_SHADE | PALETTE_TRANSLUC | PALETTE_MAIN; } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void GameInterface::app_init() { GC::AddMarkerFunc(markgcroots); @@ -568,6 +628,12 @@ void GameInterface::app_init() gMe = gView = &gPlayer[myconnectindex]; } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + static void gameInit() { gViewIndex = myconnectindex; @@ -607,6 +673,12 @@ void sndPlaySpecialMusicOrNothing(int nMusic) } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + extern IniFile* BloodINI; void GameInterface::FreeGameData() { @@ -635,6 +707,12 @@ ReservedSpace GameInterface::GetReservedScreenSpace(int viewsize) return new GameInterface; } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + enum { kLoadScreenCRC = -2051908571, diff --git a/source/games/blood/src/blood.h b/source/games/blood/src/blood.h index b552d45d6..ffb5e7f9e 100644 --- a/source/games/blood/src/blood.h +++ b/source/games/blood/src/blood.h @@ -60,19 +60,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS struct INIDESCRIPTION { - const char *pzName; - const char *pzFilename; - const char **pzArts; - int nArts; + const char* pzName; + const char* pzFilename; + const char** pzArts; + int nArts; }; struct INICHAIN { - INICHAIN *pNext; - char zName[BMAX_PATH]; - INIDESCRIPTION *pDescription; + INICHAIN* pNext; + char zName[BMAX_PATH]; + INIDESCRIPTION* pDescription; }; -extern INICHAIN *pINIChain; +extern INICHAIN* pINIChain; extern int gNetPlayers; extern int blood_globalflags; @@ -104,12 +104,12 @@ void PolymostAllocFakeSector(); inline bool DemoRecordStatus(void) { - return false; + return false; } inline bool VanillaMode() { - return false; + return false; } void sndPlaySpecialMusicOrNothing(int nMusic); @@ -136,7 +136,7 @@ struct GameInterface : public ::GameInterface void Startup() override; void Render() override; const char* GenericCheat(int player, int cheat) override; - void NewGame(MapRecord *sng, int skill, bool) override; + void NewGame(MapRecord* sng, int skill, bool) override; void NextLevel(MapRecord* map, int skill) override; void LevelCompleted(MapRecord* map, int skill) override; bool DrawAutomapPlayer(int mx, int my, int x, int y, int z, int a, double const smoothratio) override; diff --git a/source/games/blood/src/bloodactor.h b/source/games/blood/src/bloodactor.h index 839dcecaa..7802cd1ad 100644 --- a/source/games/blood/src/bloodactor.h +++ b/source/games/blood/src/bloodactor.h @@ -121,12 +121,12 @@ public: return spr.type >= kItemAmmoBase && spr.type < kItemAmmoMax; } - bool isActive() + bool isActive() { if (!hasX()) return false; - switch (xspr.aiState->stateType) + switch (xspr.aiState->stateType) { case kAiStateIdle: case kAiStateGenIdle: diff --git a/source/games/blood/src/callback.cpp b/source/games/blood/src/callback.cpp index d6fd84c1d..1b5c64fc5 100644 --- a/source/games/blood/src/callback.cpp +++ b/source/games/blood/src/callback.cpp @@ -30,725 +30,875 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void fxFlameLick(DBloodActor* actor, sectortype*) // 0 { - if (!actor) return; - int top, bottom; - GetActorExtents(actor, &top, &bottom); - for (int i = 0; i < 3; i++) - { - int nDist = (actor->spr.xrepeat*(tileWidth(actor->spr.picnum)/2))>>3; - int nAngle = Random(2048); - int dx = MulScale(nDist, Cos(nAngle), 30); - int dy = MulScale(nDist, Sin(nAngle), 30); - int x = actor->spr.pos.X + dx; - int y = actor->spr.pos.Y + dy; - int z = bottom-Random(bottom-top); - auto pFX = gFX.fxSpawnActor(FX_32, actor->spr.sector(), x, y, z, 0); - if (pFX) - { - pFX->xvel = actor->xvel + Random2(-dx); - pFX->yvel = actor->yvel + Random2(-dy); - pFX->zvel = actor->zvel - Random(0x1aaaa); - } - } - if (actor->xspr.burnTime > 0) - evPostActor(actor, 5, kCallbackFXFlameLick); + if (!actor) return; + int top, bottom; + GetActorExtents(actor, &top, &bottom); + for (int i = 0; i < 3; i++) + { + int nDist = (actor->spr.xrepeat * (tileWidth(actor->spr.picnum) / 2)) >> 3; + int nAngle = Random(2048); + int dx = MulScale(nDist, Cos(nAngle), 30); + int dy = MulScale(nDist, Sin(nAngle), 30); + int x = actor->spr.pos.X + dx; + int y = actor->spr.pos.Y + dy; + int z = bottom - Random(bottom - top); + auto pFX = gFX.fxSpawnActor(FX_32, actor->spr.sector(), x, y, z, 0); + if (pFX) + { + pFX->xvel = actor->xvel + Random2(-dx); + pFX->yvel = actor->yvel + Random2(-dy); + pFX->zvel = actor->zvel - Random(0x1aaaa); + } + } + if (actor->xspr.burnTime > 0) + evPostActor(actor, 5, kCallbackFXFlameLick); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void Remove(DBloodActor* actor, sectortype*) // 1 { - if (!actor) return; - evKillActor(actor, kCallbackFXFlareSpark); - if (actor->hasX()) - seqKill(actor); - sfxKill3DSound(actor, 0, -1); - DeleteSprite(actor); + if (!actor) return; + evKillActor(actor, kCallbackFXFlareSpark); + if (actor->hasX()) + seqKill(actor); + sfxKill3DSound(actor, 0, -1); + DeleteSprite(actor); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void FlareBurst(DBloodActor* actor, sectortype*) // 2 { - if (!actor) return; - int nAngle = getangle(actor->xvel, actor->yvel); - int nRadius = 0x55555; - for (int i = 0; i < 8; i++) - { - auto spawnedactor = actSpawnSprite(actor, 5); - spawnedactor->spr.picnum = 2424; - spawnedactor->spr.shade = -128; - spawnedactor->spr.xrepeat = spawnedactor->spr.yrepeat = 32; - spawnedactor->spr.type = kMissileFlareAlt; - spawnedactor->spr.clipdist = 2; - spawnedactor->SetOwner(actor); - int nAngle2 = (i<<11)/8; - int dx = 0; - int dy = mulscale30r(nRadius, Sin(nAngle2)); - int dz = mulscale30r(nRadius, -Cos(nAngle2)); - if (i&1) - { - dy >>= 1; - dz >>= 1; - } - RotateVector(&dx, &dy, nAngle); - spawnedactor->xvel += dx; - spawnedactor->yvel += dy; - spawnedactor->zvel += dz; - evPostActor(spawnedactor, 960, kCallbackRemove); - } - evPostActor(actor, 0, kCallbackRemove); + if (!actor) return; + int nAngle = getangle(actor->xvel, actor->yvel); + int nRadius = 0x55555; + for (int i = 0; i < 8; i++) + { + auto spawnedactor = actSpawnSprite(actor, 5); + spawnedactor->spr.picnum = 2424; + spawnedactor->spr.shade = -128; + spawnedactor->spr.xrepeat = spawnedactor->spr.yrepeat = 32; + spawnedactor->spr.type = kMissileFlareAlt; + spawnedactor->spr.clipdist = 2; + spawnedactor->SetOwner(actor); + int nAngle2 = (i << 11) / 8; + int dx = 0; + int dy = mulscale30r(nRadius, Sin(nAngle2)); + int dz = mulscale30r(nRadius, -Cos(nAngle2)); + if (i & 1) + { + dy >>= 1; + dz >>= 1; + } + RotateVector(&dx, &dy, nAngle); + spawnedactor->xvel += dx; + spawnedactor->yvel += dy; + spawnedactor->zvel += dz; + evPostActor(spawnedactor, 960, kCallbackRemove); + } + evPostActor(actor, 0, kCallbackRemove); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void fxFlareSpark(DBloodActor* actor, sectortype*) // 3 { - if (!actor) return; - auto pFX = gFX.fxSpawnActor(FX_28, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); - if (pFX) - { - pFX->xvel = actor->xvel + Random2(0x1aaaa); - pFX->yvel = actor->yvel + Random2(0x1aaaa); - pFX->zvel = actor->zvel - Random(0x1aaaa); - } - evPostActor(actor, 4, kCallbackFXFlareSpark); + if (!actor) return; + auto pFX = gFX.fxSpawnActor(FX_28, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); + if (pFX) + { + pFX->xvel = actor->xvel + Random2(0x1aaaa); + pFX->yvel = actor->yvel + Random2(0x1aaaa); + pFX->zvel = actor->zvel - Random(0x1aaaa); + } + evPostActor(actor, 4, kCallbackFXFlareSpark); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void fxFlareSparkLite(DBloodActor* actor, sectortype*) // 4 { - if (!actor) return; - auto pFX = gFX.fxSpawnActor(FX_28, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); - if (pFX) - { - pFX->xvel = actor->xvel + Random2(0x1aaaa); - pFX->yvel = actor->yvel + Random2(0x1aaaa); - pFX->zvel = actor->zvel - Random(0x1aaaa); - } - evPostActor(actor, 12, kCallbackFXFlareSparkLite); + if (!actor) return; + auto pFX = gFX.fxSpawnActor(FX_28, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); + if (pFX) + { + pFX->xvel = actor->xvel + Random2(0x1aaaa); + pFX->yvel = actor->yvel + Random2(0x1aaaa); + pFX->zvel = actor->zvel - Random(0x1aaaa); + } + evPostActor(actor, 12, kCallbackFXFlareSparkLite); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void fxZombieBloodSpurt(DBloodActor* actor, sectortype*) // 5 { - if (!actor) return; - assert(actor->hasX()); - int top, bottom; - GetActorExtents(actor, &top, &bottom); - auto pFX = gFX.fxSpawnActor(FX_27, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, top, 0); - if (pFX) - { - pFX->xvel = actor->xvel + Random2(0x11111); - pFX->yvel = actor->yvel + Random2(0x11111); - pFX->zvel = actor->zvel - 0x6aaaa; - } - if (actor->xspr.data1 > 0) - { - evPostActor(actor, 4, kCallbackFXZombieSpurt); - actor->xspr.data1 -= 4; - } - else if (actor->xspr.data2 > 0) - { - evPostActor(actor, 60, kCallbackFXZombieSpurt); - actor->xspr.data1 = 40; - actor->xspr.data2--; - } + if (!actor) return; + assert(actor->hasX()); + int top, bottom; + GetActorExtents(actor, &top, &bottom); + auto pFX = gFX.fxSpawnActor(FX_27, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, top, 0); + if (pFX) + { + pFX->xvel = actor->xvel + Random2(0x11111); + pFX->yvel = actor->yvel + Random2(0x11111); + pFX->zvel = actor->zvel - 0x6aaaa; + } + if (actor->xspr.data1 > 0) + { + evPostActor(actor, 4, kCallbackFXZombieSpurt); + actor->xspr.data1 -= 4; + } + else if (actor->xspr.data2 > 0) + { + evPostActor(actor, 60, kCallbackFXZombieSpurt); + actor->xspr.data1 = 40; + actor->xspr.data2--; + } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void fxBloodSpurt(DBloodActor* actor, sectortype*) // 6 { - if (!actor) return; - auto pFX = gFX.fxSpawnActor(FX_27, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); - if (pFX) - { - pFX->spr.ang = 0; - pFX->xvel = actor->xvel>>8; - pFX->yvel = actor->yvel>>8; - pFX->zvel = actor->zvel>>8; - } - evPostActor(actor, 6, kCallbackFXBloodSpurt); + if (!actor) return; + auto pFX = gFX.fxSpawnActor(FX_27, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); + if (pFX) + { + pFX->spr.ang = 0; + pFX->xvel = actor->xvel >> 8; + pFX->yvel = actor->yvel >> 8; + pFX->zvel = actor->zvel >> 8; + } + evPostActor(actor, 6, kCallbackFXBloodSpurt); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- void fxArcSpark(DBloodActor* actor, sectortype*) // 7 { - if (!actor) return; - auto pFX = gFX.fxSpawnActor(FX_15, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); - if (pFX) - { - pFX->xvel = actor->xvel + Random2(0x10000); - pFX->yvel = actor->yvel + Random2(0x10000); - pFX->zvel = actor->zvel - Random(0x1aaaa); - } - evPostActor(actor, 3, kCallbackFXArcSpark); + if (!actor) return; + auto pFX = gFX.fxSpawnActor(FX_15, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); + if (pFX) + { + pFX->xvel = actor->xvel + Random2(0x10000); + pFX->yvel = actor->yvel + Random2(0x10000); + pFX->zvel = actor->zvel - Random(0x1aaaa); + } + evPostActor(actor, 3, kCallbackFXArcSpark); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- void fxDynPuff(DBloodActor* actor, sectortype*) // 8 { - if (!actor) return; - if (actor->zvel) - { - int nDist = (actor->spr.xrepeat*(tileWidth(actor->spr.picnum)/2))>>2; - int x = actor->spr.pos.X + MulScale(nDist, Cos(actor->spr.ang-512), 30); - int y = actor->spr.pos.Y + MulScale(nDist, Sin(actor->spr.ang-512), 30); - int z = actor->spr.pos.Z; - auto pFX = gFX.fxSpawnActor(FX_7, actor->spr.sector(), x, y, z, 0); - if (pFX) - { - pFX->xvel = actor->xvel; - pFX->yvel = actor->yvel; - pFX->zvel = actor->zvel; - } - } - evPostActor(actor, 12, kCallbackFXDynPuff); + if (!actor) return; + if (actor->zvel) + { + int nDist = (actor->spr.xrepeat * (tileWidth(actor->spr.picnum) / 2)) >> 2; + int x = actor->spr.pos.X + MulScale(nDist, Cos(actor->spr.ang - 512), 30); + int y = actor->spr.pos.Y + MulScale(nDist, Sin(actor->spr.ang - 512), 30); + int z = actor->spr.pos.Z; + auto pFX = gFX.fxSpawnActor(FX_7, actor->spr.sector(), x, y, z, 0); + if (pFX) + { + pFX->xvel = actor->xvel; + pFX->yvel = actor->yvel; + pFX->zvel = actor->zvel; + } + } + evPostActor(actor, 12, kCallbackFXDynPuff); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void Respawn(DBloodActor* actor, sectortype*) // 9 { - if (!actor) return; - assert(actor->hasX()); - - if (actor->spr.statnum != kStatRespawn && actor->spr.statnum != kStatThing) { - viewSetSystemMessage("Sprite #%d is not on Respawn or Thing list\n", actor->GetIndex()); - return; - } else if (!(actor->spr.flags & kHitagRespawn)) { - viewSetSystemMessage("Sprite #%d does not have the respawn attribute\n", actor->GetIndex()); - return; - } + if (!actor) return; + assert(actor->hasX()); - switch (actor->xspr.respawnPending) { - case 1: { - int nTime = MulScale(actGetRespawnTime(actor), 0x4000, 16); - actor->xspr.respawnPending = 2; - evPostActor(actor, nTime, kCallbackRespawn); - break; - } - case 2: { - int nTime = MulScale(actGetRespawnTime(actor), 0x2000, 16); - actor->xspr.respawnPending = 3; - evPostActor(actor, nTime, kCallbackRespawn); - break; - } - case 3: { - assert(actor->spr.owner != kStatRespawn); - assert(actor->spr.owner >= 0 && actor->spr.owner < kMaxStatus); - ChangeActorStat(actor, actor->spr.owner); - actor->spr.type = actor->spr.inittype; - actor->SetOwner(nullptr); - actor->spr.flags &= ~kHitagRespawn; - actor->xvel = actor->yvel = actor->zvel = 0; - actor->xspr.respawnPending = 0; - actor->xspr.burnTime = 0; - actor->xspr.isTriggered = 0; - if (actor->IsDudeActor()) - { - int nType = actor->spr.type-kDudeBase; - actor->spr.pos = actor->basePoint; - actor->spr.cstat |= CSTAT_SPRITE_BLOOD_BIT1 | CSTAT_SPRITE_BLOCK_ALL; - #ifdef NOONE_EXTENSIONS - if (!gModernMap || actor->xspr.sysData2 <= 0) actor->xspr.health = dudeInfo[actor->spr.type - kDudeBase].startHealth << 4; - else actor->xspr.health = ClipRange(actor->xspr.sysData2 << 4, 1, 65535); + if (actor->spr.statnum != kStatRespawn && actor->spr.statnum != kStatThing) { + viewSetSystemMessage("Sprite #%d is not on Respawn or Thing list\n", actor->GetIndex()); + return; + } + else if (!(actor->spr.flags & kHitagRespawn)) { + viewSetSystemMessage("Sprite #%d does not have the respawn attribute\n", actor->GetIndex()); + return; + } - switch (actor->spr.type) { - default: - actor->spr.clipdist = getDudeInfo(nType + kDudeBase)->clipdist; - if (getSequence(getDudeInfo(nType + kDudeBase)->seqStartID)) - seqSpawn(getDudeInfo(nType + kDudeBase)->seqStartID, actor, -1); - break; - case kDudeModernCustom: - seqSpawn(genDudeSeqStartId(actor), actor, -1); - break; - } - - // return dude to the patrol state - if (gModernMap && actor->xspr.dudeFlag4) { - actor->xspr.data3 = 0; - actor->SetTarget(nullptr); - } - #else - actor->spr.clipdist = getDudeInfo(nType + kDudeBase)->clipdist; - actor->xspr.health = getDudeInfo(nType + kDudeBase)->startHealth << 4; - if (getSequence(getDudeInfo(nType + kDudeBase)->seqStartID)) - seqSpawn(getDudeInfo(nType + kDudeBase)->seqStartID, actor, -1); - #endif - aiInitSprite(actor); - actor->xspr.key = 0; - } else if (actor->spr.type == kThingTNTBarrel) { - actor->spr.cstat |= CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN; - actor->spr.cstat &= ~CSTAT_SPRITE_INVISIBLE; - } + switch (actor->xspr.respawnPending) { + case 1: { + int nTime = MulScale(actGetRespawnTime(actor), 0x4000, 16); + actor->xspr.respawnPending = 2; + evPostActor(actor, nTime, kCallbackRespawn); + break; + } + case 2: { + int nTime = MulScale(actGetRespawnTime(actor), 0x2000, 16); + actor->xspr.respawnPending = 3; + evPostActor(actor, nTime, kCallbackRespawn); + break; + } + case 3: { + assert(actor->spr.owner != kStatRespawn); + assert(actor->spr.owner >= 0 && actor->spr.owner < kMaxStatus); + ChangeActorStat(actor, actor->spr.owner); + actor->spr.type = actor->spr.inittype; + actor->SetOwner(nullptr); + actor->spr.flags &= ~kHitagRespawn; + actor->xvel = actor->yvel = actor->zvel = 0; + actor->xspr.respawnPending = 0; + actor->xspr.burnTime = 0; + actor->xspr.isTriggered = 0; + if (actor->IsDudeActor()) + { + int nType = actor->spr.type - kDudeBase; + actor->spr.pos = actor->basePoint; + actor->spr.cstat |= CSTAT_SPRITE_BLOOD_BIT1 | CSTAT_SPRITE_BLOCK_ALL; +#ifdef NOONE_EXTENSIONS + if (!gModernMap || actor->xspr.sysData2 <= 0) actor->xspr.health = dudeInfo[actor->spr.type - kDudeBase].startHealth << 4; + else actor->xspr.health = ClipRange(actor->xspr.sysData2 << 4, 1, 65535); - gFX.fxSpawnActor(FX_29, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); - sfxPlay3DSound(actor, 350, -1, 0); - break; - } - } + switch (actor->spr.type) { + default: + actor->spr.clipdist = getDudeInfo(nType + kDudeBase)->clipdist; + if (getSequence(getDudeInfo(nType + kDudeBase)->seqStartID)) + seqSpawn(getDudeInfo(nType + kDudeBase)->seqStartID, actor, -1); + break; + case kDudeModernCustom: + seqSpawn(genDudeSeqStartId(actor), actor, -1); + break; + } + + // return dude to the patrol state + if (gModernMap && actor->xspr.dudeFlag4) { + actor->xspr.data3 = 0; + actor->SetTarget(nullptr); + } +#else + actor->spr.clipdist = getDudeInfo(nType + kDudeBase)->clipdist; + actor->xspr.health = getDudeInfo(nType + kDudeBase)->startHealth << 4; + if (getSequence(getDudeInfo(nType + kDudeBase)->seqStartID)) + seqSpawn(getDudeInfo(nType + kDudeBase)->seqStartID, actor, -1); +#endif + aiInitSprite(actor); + actor->xspr.key = 0; + } + else if (actor->spr.type == kThingTNTBarrel) { + actor->spr.cstat |= CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN; + actor->spr.cstat &= ~CSTAT_SPRITE_INVISIBLE; + } + + gFX.fxSpawnActor(FX_29, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); + sfxPlay3DSound(actor, 350, -1, 0); + break; + } + } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void PlayerBubble(DBloodActor* actor, sectortype*) // 10 { - if (!actor) return; - if (actor->IsPlayerActor()) - { - PLAYER *pPlayer = &gPlayer[actor->spr.type-kDudePlayer1]; - if (!pPlayer->bubbleTime) - return; - int top, bottom; - GetActorExtents(actor, &top, &bottom); - for (int i = 0; i < (pPlayer->bubbleTime>>6); i++) - { - int nDist = (actor->spr.xrepeat*(tileWidth(actor->spr.picnum)/2))>>2; - int nAngle = Random(2048); - int x = actor->spr.pos.X + MulScale(nDist, Cos(nAngle), 30); - int y = actor->spr.pos.Y + MulScale(nDist, Sin(nAngle), 30); - int z = bottom-Random(bottom-top); - auto pFX = gFX.fxSpawnActor((FX_ID)(FX_23+Random(3)), actor->spr.sector(), x, y, z, 0); - if (pFX) - { - pFX->xvel = actor->xvel + Random2(0x1aaaa); - pFX->yvel = actor->yvel + Random2(0x1aaaa); - pFX->zvel = actor->zvel + Random2(0x1aaaa); - } - } - evPostActor(actor, 4, kCallbackPlayerBubble); - } + if (!actor) return; + if (actor->IsPlayerActor()) + { + PLAYER* pPlayer = &gPlayer[actor->spr.type - kDudePlayer1]; + if (!pPlayer->bubbleTime) + return; + int top, bottom; + GetActorExtents(actor, &top, &bottom); + for (int i = 0; i < (pPlayer->bubbleTime >> 6); i++) + { + int nDist = (actor->spr.xrepeat * (tileWidth(actor->spr.picnum) / 2)) >> 2; + int nAngle = Random(2048); + int x = actor->spr.pos.X + MulScale(nDist, Cos(nAngle), 30); + int y = actor->spr.pos.Y + MulScale(nDist, Sin(nAngle), 30); + int z = bottom - Random(bottom - top); + auto pFX = gFX.fxSpawnActor((FX_ID)(FX_23 + Random(3)), actor->spr.sector(), x, y, z, 0); + if (pFX) + { + pFX->xvel = actor->xvel + Random2(0x1aaaa); + pFX->yvel = actor->yvel + Random2(0x1aaaa); + pFX->zvel = actor->zvel + Random2(0x1aaaa); + } + } + evPostActor(actor, 4, kCallbackPlayerBubble); + } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void EnemyBubble(DBloodActor* actor, sectortype*) // 11 { - if (!actor) return; - int top, bottom; - GetActorExtents(actor, &top, &bottom); - for (int i = 0; i < (abs(actor->zvel)>>18); i++) - { - int nDist = (actor->spr.xrepeat*(tileWidth(actor->spr.picnum)/2))>>2; - int nAngle = Random(2048); - int x = actor->spr.pos.X + MulScale(nDist, Cos(nAngle), 30); - int y = actor->spr.pos.Y + MulScale(nDist, Sin(nAngle), 30); - int z = bottom-Random(bottom-top); - auto pFX = gFX.fxSpawnActor((FX_ID)(FX_23+Random(3)), actor->spr.sector(), x, y, z, 0); - if (pFX) - { - pFX->xvel = actor->xvel + Random2(0x1aaaa); - pFX->yvel = actor->yvel + Random2(0x1aaaa); - pFX->zvel = actor->zvel + Random2(0x1aaaa); - } - } - evPostActor(actor, 4, kCallbackEnemeyBubble); + if (!actor) return; + int top, bottom; + GetActorExtents(actor, &top, &bottom); + for (int i = 0; i < (abs(actor->zvel) >> 18); i++) + { + int nDist = (actor->spr.xrepeat * (tileWidth(actor->spr.picnum) / 2)) >> 2; + int nAngle = Random(2048); + int x = actor->spr.pos.X + MulScale(nDist, Cos(nAngle), 30); + int y = actor->spr.pos.Y + MulScale(nDist, Sin(nAngle), 30); + int z = bottom - Random(bottom - top); + auto pFX = gFX.fxSpawnActor((FX_ID)(FX_23 + Random(3)), actor->spr.sector(), x, y, z, 0); + if (pFX) + { + pFX->xvel = actor->xvel + Random2(0x1aaaa); + pFX->yvel = actor->yvel + Random2(0x1aaaa); + pFX->zvel = actor->zvel + Random2(0x1aaaa); + } + } + evPostActor(actor, 4, kCallbackEnemeyBubble); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void CounterCheck(DBloodActor*, sectortype* pSector) // 12 { - if (!pSector || pSector->type != kSectorCounter) return; - if (!pSector->hasX()) return; - - XSECTOR* pXSector = &pSector->xs(); - int nReq = pXSector->waitTimeA; - int nType = pXSector->data; - int nCount = 0; - if (!nType || !nReq) return; - - BloodSectIterator it(pSector); - while (auto actor = it.Next()) - { - if (actor->spr.type == nType) nCount++; - } - - if (nCount < nReq) { - evPostSector(pSector, 5, kCallbackCounterCheck); - return; - } else { - //pXSector->waitTimeA = 0; //do not reset necessary objects counter to zero - trTriggerSector(pSector, kCmdOn); - pXSector->locked = 1; //lock sector, so it can be opened again later - } + if (!pSector || pSector->type != kSectorCounter) return; + if (!pSector->hasX()) return; + + XSECTOR* pXSector = &pSector->xs(); + int nReq = pXSector->waitTimeA; + int nType = pXSector->data; + int nCount = 0; + if (!nType || !nReq) return; + + BloodSectIterator it(pSector); + while (auto actor = it.Next()) + { + if (actor->spr.type == nType) nCount++; + } + + if (nCount < nReq) { + evPostSector(pSector, 5, kCallbackCounterCheck); + return; + } + else { + //pXSector->waitTimeA = 0; //do not reset necessary objects counter to zero + trTriggerSector(pSector, kCmdOn); + pXSector->locked = 1; //lock sector, so it can be opened again later + } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void FinishHim(DBloodActor* actor, sectortype*) // 13 { - if (!actor) return; - if (actor->IsPlayerActor() && playerSeqPlaying(&gPlayer[actor->spr.type - kDudePlayer1], 16) && actor == gMe->actor) - sndStartSample(3313, -1, 1, 0); + if (!actor) return; + if (actor->IsPlayerActor() && playerSeqPlaying(&gPlayer[actor->spr.type - kDudePlayer1], 16) && actor == gMe->actor) + sndStartSample(3313, -1, 1, 0); } void fxBloodBits(DBloodActor* actor, sectortype*) // 14 { - if (!actor) return; - int ceilZ, floorZ; - Collision floorColl, ceilColl; - GetZRange(actor, &ceilZ, &ceilColl, &floorZ, &floorColl, actor->spr.clipdist, CLIPMASK0); - int top, bottom; - GetActorExtents(actor, &top, &bottom); - actor->spr.pos.Z += floorZ-bottom; - int nAngle = Random(2048); - int nDist = Random(16)<<4; - int x = actor->spr.pos.X+MulScale(nDist, Cos(nAngle), 28); - int y = actor->spr.pos.Y+MulScale(nDist, Sin(nAngle), 28); - gFX.fxSpawnActor(FX_48, actor->spr.sector(), x, y, actor->spr.pos.Z, 0); - if (actor->spr.ang == 1024) - { - int nChannel = 28 + (actor->GetIndex() & 2); // this is a little stupid... - sfxPlay3DSound(actor, 385, nChannel, 1); - } - if (Chance(0x5000)) - { - auto pFX = gFX.fxSpawnActor(FX_36, actor->spr.sector(), x, y, floorZ-64, 0); - if (pFX) - pFX->spr.ang = nAngle; - } - gFX.remove(actor); + if (!actor) return; + int ceilZ, floorZ; + Collision floorColl, ceilColl; + GetZRange(actor, &ceilZ, &ceilColl, &floorZ, &floorColl, actor->spr.clipdist, CLIPMASK0); + int top, bottom; + GetActorExtents(actor, &top, &bottom); + actor->spr.pos.Z += floorZ - bottom; + int nAngle = Random(2048); + int nDist = Random(16) << 4; + int x = actor->spr.pos.X + MulScale(nDist, Cos(nAngle), 28); + int y = actor->spr.pos.Y + MulScale(nDist, Sin(nAngle), 28); + gFX.fxSpawnActor(FX_48, actor->spr.sector(), x, y, actor->spr.pos.Z, 0); + if (actor->spr.ang == 1024) + { + int nChannel = 28 + (actor->GetIndex() & 2); // this is a little stupid... + sfxPlay3DSound(actor, 385, nChannel, 1); + } + if (Chance(0x5000)) + { + auto pFX = gFX.fxSpawnActor(FX_36, actor->spr.sector(), x, y, floorZ - 64, 0); + if (pFX) + pFX->spr.ang = nAngle; + } + gFX.remove(actor); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void fxTeslaAlt(DBloodActor* actor, sectortype*) // 15 { - if (!actor) return; - auto pFX = gFX.fxSpawnActor(FX_49, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); - if (pFX) - { - pFX->xvel = actor->xvel + Random2(0x1aaaa); - pFX->yvel = actor->yvel + Random2(0x1aaaa); - pFX->zvel = actor->zvel - Random(0x1aaaa); - } - evPostActor(actor, 3, kCallbackFXTeslaAlt); + if (!actor) return; + auto pFX = gFX.fxSpawnActor(FX_49, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); + if (pFX) + { + pFX->xvel = actor->xvel + Random2(0x1aaaa); + pFX->yvel = actor->yvel + Random2(0x1aaaa); + pFX->zvel = actor->zvel - Random(0x1aaaa); + } + evPostActor(actor, 3, kCallbackFXTeslaAlt); } -int tommySleeveSnd[] = { 608, 609, 611 }; // unused? -int sawedOffSleeveSnd[] = { 610, 612 }; +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static const int tommySleeveSnd[] = { 608, 609, 611 }; // unused? +static const int sawedOffSleeveSnd[] = { 610, 612 }; void fxBouncingSleeve(DBloodActor* actor, sectortype*) // 16 { - if (!actor) return; - int ceilZ, floorZ; - Collision floorColl, ceilColl; + if (!actor) return; + int ceilZ, floorZ; + Collision floorColl, ceilColl; - GetZRange(actor, &ceilZ, &ceilColl, &floorZ, &floorColl, actor->spr.clipdist, CLIPMASK0); - int top, bottom; GetActorExtents(actor, &top, &bottom); - actor->spr.pos.Z += floorZ - bottom; - - int zv = actor->zvel - actor->spr.sector()->velFloor; - - if (actor->zvel == 0) sleeveStopBouncing(actor); - else if (zv > 0) { - actFloorBounceVector((int*)& actor->xvel, (int*)& actor->yvel, &zv, actor->spr.sector(), 0x9000); - actor->zvel = zv; - if (actor->spr.sector()->velFloor == 0 && abs(actor->zvel) < 0x20000) { - sleeveStopBouncing(actor); - return; - } + GetZRange(actor, &ceilZ, &ceilColl, &floorZ, &floorColl, actor->spr.clipdist, CLIPMASK0); + int top, bottom; GetActorExtents(actor, &top, &bottom); + actor->spr.pos.Z += floorZ - bottom; - int nChannel = 28 + (actor->GetIndex() & 2); - - // tommy sleeve - if (actor->spr.type >= 37 && actor->spr.type <= 39) { - Random(3); - sfxPlay3DSound(actor, 608 + Random(2), nChannel, 1); - - // sawed-off sleeve - } else { - sfxPlay3DSound(actor, sawedOffSleeveSnd[Random(2)], nChannel, 1); - } - } + int zv = actor->zvel - actor->spr.sector()->velFloor; + + if (actor->zvel == 0) sleeveStopBouncing(actor); + else if (zv > 0) { + actFloorBounceVector((int*)&actor->xvel, (int*)&actor->yvel, &zv, actor->spr.sector(), 0x9000); + actor->zvel = zv; + if (actor->spr.sector()->velFloor == 0 && abs(actor->zvel) < 0x20000) { + sleeveStopBouncing(actor); + return; + } + + int nChannel = 28 + (actor->GetIndex() & 2); + + // tommy sleeve + if (actor->spr.type >= 37 && actor->spr.type <= 39) { + Random(3); + sfxPlay3DSound(actor, 608 + Random(2), nChannel, 1); + + // sawed-off sleeve + } + else { + sfxPlay3DSound(actor, sawedOffSleeveSnd[Random(2)], nChannel, 1); + } + } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- -void sleeveStopBouncing(DBloodActor* actor) +void sleeveStopBouncing(DBloodActor* actor) { - actor->xvel = actor->yvel = actor->zvel = 0; - if (actor->hasX()) seqKill(actor); - sfxKill3DSound(actor, -1, -1); + actor->xvel = actor->yvel = actor->zvel = 0; + if (actor->hasX()) seqKill(actor); + sfxKill3DSound(actor, -1, -1); - switch (actor->spr.type) { - case 37: - case 38: - case 39: - actor->spr.picnum = 2465; - break; - case 40: - case 41: - case 42: - actor->spr.picnum = 2464; - break; - } + switch (actor->spr.type) { + case 37: + case 38: + case 39: + actor->spr.picnum = 2465; + break; + case 40: + case 41: + case 42: + actor->spr.picnum = 2464; + break; + } - actor->spr.type = 51; - actor->spr.xrepeat = actor->spr.yrepeat = 10; + actor->spr.type = 51; + actor->spr.xrepeat = actor->spr.yrepeat = 10; } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void returnFlagToBase(DBloodActor* actor, sectortype*) // 17 { - if (!actor) return; - auto aOwner = actor->GetOwner(); - if (aOwner) - { - switch (actor->spr.type) - { - case kItemFlagA: - trTriggerSprite(aOwner, kCmdOn); - sndStartSample(8003, 255, 2, 0); - gBlueFlagDropped = false; - viewSetMessage("Blue Flag returned to base."); - break; - case kItemFlagB: - trTriggerSprite(aOwner, kCmdOn); - sndStartSample(8002, 255, 2, 0); - gRedFlagDropped = false; - viewSetMessage("Red Flag returned to base."); - break; - } - } - evPostActor(actor, 0, kCallbackRemove); + if (!actor) return; + auto aOwner = actor->GetOwner(); + if (aOwner) + { + switch (actor->spr.type) + { + case kItemFlagA: + trTriggerSprite(aOwner, kCmdOn); + sndStartSample(8003, 255, 2, 0); + gBlueFlagDropped = false; + viewSetMessage("Blue Flag returned to base."); + break; + case kItemFlagB: + trTriggerSprite(aOwner, kCmdOn); + sndStartSample(8002, 255, 2, 0); + gRedFlagDropped = false; + viewSetMessage("Red Flag returned to base."); + break; + } + } + evPostActor(actor, 0, kCallbackRemove); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void fxPodBloodSpray(DBloodActor* actor, sectortype*) // 18 { - if (!actor) return; - DBloodActor* pFX; - if (actor->spr.type == 53) - pFX = gFX.fxSpawnActor(FX_53, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); - else - pFX = gFX.fxSpawnActor(FX_54, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); - if (pFX) - { - pFX->spr.ang = 0; - pFX->xvel = actor->xvel >> 8; - pFX->yvel = actor->yvel >> 8; - pFX->zvel = actor->zvel >> 8; - } - evPostActor(actor, 6, kCallbackFXPodBloodSpray); + if (!actor) return; + DBloodActor* pFX; + if (actor->spr.type == 53) + pFX = gFX.fxSpawnActor(FX_53, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); + else + pFX = gFX.fxSpawnActor(FX_54, actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, 0); + if (pFX) + { + pFX->spr.ang = 0; + pFX->xvel = actor->xvel >> 8; + pFX->yvel = actor->yvel >> 8; + pFX->zvel = actor->zvel >> 8; + } + evPostActor(actor, 6, kCallbackFXPodBloodSpray); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void fxPodBloodSplat(DBloodActor* actor, sectortype*) // 19 { - if (!actor) return; - int ceilZ, floorZ; - Collision floorColl, ceilColl; + if (!actor) return; + int ceilZ, floorZ; + Collision floorColl, ceilColl; - GetZRange(actor, &ceilZ, &ceilColl, &floorZ, &floorColl, actor->spr.clipdist, CLIPMASK0); - int top, bottom; - GetActorExtents(actor, &top, &bottom); - actor->spr.pos.Z += floorZ-bottom; - int nAngle = Random(2048); - int nDist = Random(16)<<4; - int x = actor->spr.pos.X+MulScale(nDist, Cos(nAngle), 28); - int y = actor->spr.pos.Y+MulScale(nDist, Sin(nAngle), 28); - if (actor->spr.ang == 1024) - { - int nChannel = 28 + (actor->GetIndex() & 2); - assert(nChannel < 32); - sfxPlay3DSound(actor, 385, nChannel, 1); - } - DBloodActor *pFX = NULL; - if (actor->spr.type == 53 || actor->spr.type == kThingPodGreenBall) - { - if (Chance(0x500) || actor->spr.type == kThingPodGreenBall) - pFX = gFX.fxSpawnActor(FX_55, actor->spr.sector(), x, y, floorZ-64, 0); - if (pFX) - pFX->spr.ang = nAngle; - } - else - { - pFX = gFX.fxSpawnActor(FX_32, actor->spr.sector(), x, y, floorZ-64, 0); - if (pFX) - pFX->spr.ang = nAngle; - } - gFX.remove(actor); + GetZRange(actor, &ceilZ, &ceilColl, &floorZ, &floorColl, actor->spr.clipdist, CLIPMASK0); + int top, bottom; + GetActorExtents(actor, &top, &bottom); + actor->spr.pos.Z += floorZ - bottom; + int nAngle = Random(2048); + int nDist = Random(16) << 4; + int x = actor->spr.pos.X + MulScale(nDist, Cos(nAngle), 28); + int y = actor->spr.pos.Y + MulScale(nDist, Sin(nAngle), 28); + if (actor->spr.ang == 1024) + { + int nChannel = 28 + (actor->GetIndex() & 2); + assert(nChannel < 32); + sfxPlay3DSound(actor, 385, nChannel, 1); + } + DBloodActor* pFX = NULL; + if (actor->spr.type == 53 || actor->spr.type == kThingPodGreenBall) + { + if (Chance(0x500) || actor->spr.type == kThingPodGreenBall) + pFX = gFX.fxSpawnActor(FX_55, actor->spr.sector(), x, y, floorZ - 64, 0); + if (pFX) + pFX->spr.ang = nAngle; + } + else + { + pFX = gFX.fxSpawnActor(FX_32, actor->spr.sector(), x, y, floorZ - 64, 0); + if (pFX) + pFX->spr.ang = nAngle; + } + gFX.remove(actor); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- void LeechStateTimer(DBloodActor* actor, sectortype*) // 20 { - if (!actor) return; - if (actor->spr.statnum == kStatThing && !(actor->spr.flags & 32)) { - switch (actor->spr.type) { - case kThingDroppedLifeLeech: - #ifdef NOONE_EXTENSIONS - case kModernThingEnemyLifeLeech: - #endif - actor->xspr.stateTimer = 0; - break; - } - } + if (!actor) return; + if (actor->spr.statnum == kStatThing && !(actor->spr.flags & 32)) { + switch (actor->spr.type) { + case kThingDroppedLifeLeech: +#ifdef NOONE_EXTENSIONS + case kModernThingEnemyLifeLeech: +#endif + actor->xspr.stateTimer = 0; + break; + } + } } -void sub_76A08(DBloodActor *actor, DBloodActor *actor2, PLAYER *pPlayer) // ??? +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void sub_76A08(DBloodActor* actor, DBloodActor* actor2, PLAYER* pPlayer) // ??? { - int top, bottom; - GetActorExtents(actor, &top, &bottom); - actor->spr.pos.X = actor2->spr.pos.X; - actor->spr.pos.Y = actor2->spr.pos.Y; - actor->spr.pos.Z = actor2->spr.sector()->floorz-(bottom-actor->spr.pos.Z); - actor->spr.ang = actor2->spr.ang; - ChangeActorSect(actor, actor2->spr.sector()); - sfxPlay3DSound(actor2, 201, -1, 0); - actor->xvel = actor->yvel = actor->zvel = 0; - viewBackupSpriteLoc(actor); - if (pPlayer) - { - playerResetInertia(pPlayer); - pPlayer->zViewVel = pPlayer->zWeaponVel = 0; - } + int top, bottom; + GetActorExtents(actor, &top, &bottom); + actor->spr.pos.X = actor2->spr.pos.X; + actor->spr.pos.Y = actor2->spr.pos.Y; + actor->spr.pos.Z = actor2->spr.sector()->floorz - (bottom - actor->spr.pos.Z); + actor->spr.ang = actor2->spr.ang; + ChangeActorSect(actor, actor2->spr.sector()); + sfxPlay3DSound(actor2, 201, -1, 0); + actor->xvel = actor->yvel = actor->zvel = 0; + viewBackupSpriteLoc(actor); + if (pPlayer) + { + playerResetInertia(pPlayer); + pPlayer->zViewVel = pPlayer->zWeaponVel = 0; + } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void DropVoodooCb(DBloodActor* actor, sectortype*) // unused { - if (!actor) return; - auto Owner = actor->GetOwner(); - if (Owner == nullptr) - { - evPostActor(actor, 0, kCallbackRemove); - return; - } - PLAYER *pPlayer; - if (Owner->IsPlayerActor()) - pPlayer = &gPlayer[Owner->spr.type-kDudePlayer1]; - else - pPlayer = nullptr; - if (!pPlayer) - { - evPostActor(actor, 0, kCallbackRemove); - return; - } - actor->spr.ang = getangle(Owner->spr.pos.X-actor->spr.pos.X, Owner->spr.pos.Y-actor->spr.pos.Y); - if (actor->hasX()) - { - if (actor->xspr.data1 == 0) - { - evPostActor(actor, 0, kCallbackRemove); - return; - } + if (!actor) return; + auto Owner = actor->GetOwner(); + if (Owner == nullptr) + { + evPostActor(actor, 0, kCallbackRemove); + return; + } + PLAYER* pPlayer; + if (Owner->IsPlayerActor()) + pPlayer = &gPlayer[Owner->spr.type - kDudePlayer1]; + else + pPlayer = nullptr; + if (!pPlayer) + { + evPostActor(actor, 0, kCallbackRemove); + return; + } + actor->spr.ang = getangle(Owner->spr.pos.X - actor->spr.pos.X, Owner->spr.pos.Y - actor->spr.pos.Y); + if (actor->hasX()) + { + if (actor->xspr.data1 == 0) + { + evPostActor(actor, 0, kCallbackRemove); + return; + } - BloodStatIterator it(kStatDude); - while (auto actor2 = it.Next()) - { - auto nextactor = it.Peek(); - if (Owner == actor2) - continue; - if (actor2->hasX()) - { - PLAYER *pPlayer2; - if (actor2->IsPlayerActor()) - pPlayer2 = &gPlayer[actor2->spr.type-kDudePlayer1]; - else - pPlayer2 = nullptr; + BloodStatIterator it(kStatDude); + while (auto actor2 = it.Next()) + { + auto nextactor = it.Peek(); + if (Owner == actor2) + continue; + if (actor2->hasX()) + { + PLAYER* pPlayer2; + if (actor2->IsPlayerActor()) + pPlayer2 = &gPlayer[actor2->spr.type - kDudePlayer1]; + else + pPlayer2 = nullptr; - if (actor2->xspr.health > 0 && (pPlayer2 || actor2->xspr.key == 0)) - { - if (pPlayer2) - { - if (gGameOptions.nGameType == 1) - continue; - if (gGameOptions.nGameType == 3 && pPlayer->teamId == pPlayer2->teamId) - continue; - int t = 0x8000/ClipLow(gNetPlayers-1, 1); - if (!powerupCheck(pPlayer2, kPwUpDeathMask)) - t += ((3200-pPlayer2->armor[2])<<15)/3200; - if (Chance(t) || nextactor == nullptr) - { - int nDmg = actDamageSprite(actor, actor2, kDamageSpirit, actor->xspr.data1<<4); - actor->xspr.data1 = ClipLow(actor->xspr.data1-nDmg, 0); - sub_76A08(actor2, actor, pPlayer2); - evPostActor(actor, 0, kCallbackRemove); - return; - } - } - else - { - int vd = 0x2666; - switch (actor2->spr.type) - { - case kDudeBoneEel: - case kDudeBat: - case kDudeRat: - case kDudeTinyCaleb: - case kDudeBeast: - vd = 0x147; - break; - case kDudeZombieAxeBuried: - case kDudePodGreen: - case kDudeTentacleGreen: - case kDudePodFire: - case kDudeTentacleFire: - case kDudePodMother: - case kDudeTentacleMother: - case kDudeCerberusTwoHead: - case kDudeCerberusOneHead: - case kDudeTchernobog: - case kDudeBurningInnocent: - case kDudeBurningCultist: - case kDudeBurningZombieAxe: - case kDudeBurningZombieButcher: - case kDudeCultistReserved: - case kDudeZombieAxeLaying: - case kDudeInnocent: - case kDudeBurningTinyCaleb: - case kDudeBurningBeast: - vd = 0; - break; - } - if (vd && (Chance(vd) || nextactor == nullptr)) - { - sub_76A08(actor2, actor, NULL); - evPostActor(actor, 0, kCallbackRemove); - return; - } - } - } - } - } - actor->xspr.data1 = ClipLow(actor->xspr.data1-1, 0); - evPostActor(actor, 0, kCallbackRemove); - } + if (actor2->xspr.health > 0 && (pPlayer2 || actor2->xspr.key == 0)) + { + if (pPlayer2) + { + if (gGameOptions.nGameType == 1) + continue; + if (gGameOptions.nGameType == 3 && pPlayer->teamId == pPlayer2->teamId) + continue; + int t = 0x8000 / ClipLow(gNetPlayers - 1, 1); + if (!powerupCheck(pPlayer2, kPwUpDeathMask)) + t += ((3200 - pPlayer2->armor[2]) << 15) / 3200; + if (Chance(t) || nextactor == nullptr) + { + int nDmg = actDamageSprite(actor, actor2, kDamageSpirit, actor->xspr.data1 << 4); + actor->xspr.data1 = ClipLow(actor->xspr.data1 - nDmg, 0); + sub_76A08(actor2, actor, pPlayer2); + evPostActor(actor, 0, kCallbackRemove); + return; + } + } + else + { + int vd = 0x2666; + switch (actor2->spr.type) + { + case kDudeBoneEel: + case kDudeBat: + case kDudeRat: + case kDudeTinyCaleb: + case kDudeBeast: + vd = 0x147; + break; + case kDudeZombieAxeBuried: + case kDudePodGreen: + case kDudeTentacleGreen: + case kDudePodFire: + case kDudeTentacleFire: + case kDudePodMother: + case kDudeTentacleMother: + case kDudeCerberusTwoHead: + case kDudeCerberusOneHead: + case kDudeTchernobog: + case kDudeBurningInnocent: + case kDudeBurningCultist: + case kDudeBurningZombieAxe: + case kDudeBurningZombieButcher: + case kDudeCultistReserved: + case kDudeZombieAxeLaying: + case kDudeInnocent: + case kDudeBurningTinyCaleb: + case kDudeBurningBeast: + vd = 0; + break; + } + if (vd && (Chance(vd) || nextactor == nullptr)) + { + sub_76A08(actor2, actor, NULL); + evPostActor(actor, 0, kCallbackRemove); + return; + } + } + } + } + } + actor->xspr.data1 = ClipLow(actor->xspr.data1 - 1, 0); + evPostActor(actor, 0, kCallbackRemove); + } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void callbackCondition(DBloodActor* actor, sectortype*) { - if (actor->xspr.isTriggered) return; + if (actor->xspr.isTriggered) return; - TRCONDITION const* pCond = &gCondition[actor->xspr.sysData1]; - for (unsigned i = 0; i < pCond->length; i++) { - EVENT evn; - evn.target = pCond->obj[i].obj; - evn.cmd = pCond->obj[i].cmd; - evn.funcID = kCallbackCondition; - useCondition(actor, evn); - } + TRCONDITION const* pCond = &gCondition[actor->xspr.sysData1]; + for (unsigned i = 0; i < pCond->length; i++) { + EVENT evn; + evn.target = pCond->obj[i].obj; + evn.cmd = pCond->obj[i].cmd; + evn.funcID = kCallbackCondition; + useCondition(actor, evn); + } - evPostActor(actor, actor->xspr.busyTime, kCallbackCondition); - return; + evPostActor(actor, actor->xspr.busyTime, kCallbackCondition); + return; } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void(*gCallback[kCallbackMax])(DBloodActor*, sectortype*) = { - fxFlameLick, - Remove, - FlareBurst, - fxFlareSpark, - fxFlareSparkLite, - fxZombieBloodSpurt, - fxBloodSpurt, - fxArcSpark, - fxDynPuff, - Respawn, - PlayerBubble, - EnemyBubble, - CounterCheck, - FinishHim, - fxBloodBits, - fxTeslaAlt, - fxBouncingSleeve, - returnFlagToBase, - fxPodBloodSpray, - fxPodBloodSplat, - LeechStateTimer, - DropVoodooCb, // unused - #ifdef NOONE_EXTENSIONS - callbackUniMissileBurst, // the code is in nnexts.cpp - callbackMakeMissileBlocking, // the code is in nnexts.cpp - callbackGenDudeUpdate, // the code is in nnexts.cpp - callbackCondition, - #endif + fxFlameLick, + Remove, + FlareBurst, + fxFlareSpark, + fxFlareSparkLite, + fxZombieBloodSpurt, + fxBloodSpurt, + fxArcSpark, + fxDynPuff, + Respawn, + PlayerBubble, + EnemyBubble, + CounterCheck, + FinishHim, + fxBloodBits, + fxTeslaAlt, + fxBouncingSleeve, + returnFlagToBase, + fxPodBloodSpray, + fxPodBloodSplat, + LeechStateTimer, + DropVoodooCb, // unused + #ifdef NOONE_EXTENSIONS + callbackUniMissileBurst, // the code is in nnexts.cpp + callbackMakeMissileBlocking, // the code is in nnexts.cpp + callbackGenDudeUpdate, // the code is in nnexts.cpp + callbackCondition, + #endif }; END_BLD_NS diff --git a/source/games/blood/src/callback.h b/source/games/blood/src/callback.h index 0a9a235bc..59d9c6361 100644 --- a/source/games/blood/src/callback.h +++ b/source/games/blood/src/callback.h @@ -26,36 +26,36 @@ BEGIN_BLD_NS void sleeveStopBouncing(DBloodActor* pSprite); enum CALLBACK_ID { - kCallbackNone = -1, - kCallbackFXFlameLick = 0, - kCallbackRemove = 1, - kCallbackFXFlareBurst = 2, - kCallbackFXFlareSpark = 3, - kCallbackFXFlareSparkLite = 4, - kCallbackFXZombieSpurt = 5, - kCallbackFXBloodSpurt = 6, - kCallbackFXArcSpark = 7, - kCallbackFXDynPuff = 8, - kCallbackRespawn = 9, - kCallbackPlayerBubble = 10, - kCallbackEnemeyBubble = 11, - kCallbackCounterCheck = 12, - kCallbackFinishHim = 13, - kCallbackFXBloodBits = 14, - kCallbackFXTeslaAlt = 15, - kCallbackFXBouncingSleeve = 16, - kCallbackReturnFlag = 17, - kCallbackFXPodBloodSpray = 18, - kCallbackFXPodBloodSplat = 19, - kCallbackLeechStateTimer = 20, - kCallbackDropVoodoo = 21, // unused - #ifdef NOONE_EXTENSIONS - kCallbackMissileBurst = 22, - kCallbackMissileSpriteBlock = 23, - kCallbackGenDudeUpdate = 24, - kCallbackCondition = 25, - #endif - kCallbackMax, + kCallbackNone = -1, + kCallbackFXFlameLick = 0, + kCallbackRemove = 1, + kCallbackFXFlareBurst = 2, + kCallbackFXFlareSpark = 3, + kCallbackFXFlareSparkLite = 4, + kCallbackFXZombieSpurt = 5, + kCallbackFXBloodSpurt = 6, + kCallbackFXArcSpark = 7, + kCallbackFXDynPuff = 8, + kCallbackRespawn = 9, + kCallbackPlayerBubble = 10, + kCallbackEnemeyBubble = 11, + kCallbackCounterCheck = 12, + kCallbackFinishHim = 13, + kCallbackFXBloodBits = 14, + kCallbackFXTeslaAlt = 15, + kCallbackFXBouncingSleeve = 16, + kCallbackReturnFlag = 17, + kCallbackFXPodBloodSpray = 18, + kCallbackFXPodBloodSplat = 19, + kCallbackLeechStateTimer = 20, + kCallbackDropVoodoo = 21, // unused +#ifdef NOONE_EXTENSIONS + kCallbackMissileBurst = 22, + kCallbackMissileSpriteBlock = 23, + kCallbackGenDudeUpdate = 24, + kCallbackCondition = 25, +#endif + kCallbackMax, }; extern void(*gCallback[kCallbackMax])(DBloodActor*, sectortype*); diff --git a/source/games/blood/src/choke.cpp b/source/games/blood/src/choke.cpp index ebe501cc4..870b39645 100644 --- a/source/games/blood/src/choke.cpp +++ b/source/games/blood/src/choke.cpp @@ -29,6 +29,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void CChoke::init(int a1, void(*a2)(PLAYER*)) { callback = a2; @@ -44,6 +50,12 @@ void CChoke::init(int a1, void(*a2)(PLAYER*)) } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void CChoke::animateChoke(int x, int y, int smoothratio) { if (!qav) @@ -64,6 +76,12 @@ void CChoke::animateChoke(int x, int y, int smoothratio) } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void chokeCallback(PLAYER* pPlayer) { int t = gGameOptions.nDifficulty + 2; diff --git a/source/games/blood/src/common_game.h b/source/games/blood/src/common_game.h index bdb8b6a00..639756f7a 100644 --- a/source/games/blood/src/common_game.h +++ b/source/games/blood/src/common_game.h @@ -36,453 +36,453 @@ void QuitGame(void); enum { - kMagicOwner = 16383, + kMagicOwner = 16383, - kMaxTiles = MAXTILES, - kMaxStatus = MAXSTATUS, - kMaxPlayers = 8, - kMaxVoxels = MAXVOXELS, + kMaxTiles = MAXTILES, + kMaxStatus = MAXSTATUS, + kMaxPlayers = 8, + kMaxVoxels = MAXVOXELS, - kTicRate = 120, - kTicsPerFrame = 4, - kTicsPerSec = (kTicRate / kTicsPerFrame), + kTicRate = 120, + kTicsPerFrame = 4, + kTicsPerSec = (kTicRate / kTicsPerFrame), - kExplodeMax = 8, + kExplodeMax = 8, - kLensSize = 80, - kViewEffectMax = 20, + kLensSize = 80, + kViewEffectMax = 20, - kNoTile = -1, + kNoTile = -1, - //= = = = // = defined = by = NoOne: - //= = = = // = ------------------------------- + //= = = = // = defined = by = NoOne: + //= = = = // = ------------------------------- - kMaxPAL = 5, - kUserPLUStart = 15, + kMaxPAL = 5, + kUserPLUStart = 15, - kDmgFall = 0, - kDmgBurn = 1, - kDmgBullet = 2, - kDmgExplode = 3, - kDmgChoke = 4, - kDmgSpirit = 5, - kDmgElectric = 6, - kDmgMax = 7, + kDmgFall = 0, + kDmgBurn = 1, + kDmgBullet = 2, + kDmgExplode = 3, + kDmgChoke = 4, + kDmgSpirit = 5, + kDmgElectric = 6, + kDmgMax = 7, }; // MEDIUM ///////////////////////////////////////////////////// enum { -kMediumNormal = 0, -kMediumWater = 1, -kMediumGoo = 2, + kMediumNormal = 0, + kMediumWater = 1, + kMediumGoo = 2, }; // STATNUMS ///////////////////////////////////////////////////// enum { -kStatDecoration = 0, -kStatFX = 1, -kStatExplosion = 2, -kStatItem = 3, -kStatThing = 4, -kStatProjectile = 5, -kStatDude = 6, -kStatInactive = 7, // inactive (ambush) dudes -kStatRespawn = 8, -kStatPurge = 9, -kStatMarker = 10, -kStatTraps = 11, -kStatAmbience = 12, -kStatSpares = 13, -kStatFlare = 14, -kStatDebris = 15, -kStatPathMarker = 16, -kStatFree = 1024, + kStatDecoration = 0, + kStatFX = 1, + kStatExplosion = 2, + kStatItem = 3, + kStatThing = 4, + kStatProjectile = 5, + kStatDude = 6, + kStatInactive = 7, // inactive (ambush) dudes + kStatRespawn = 8, + kStatPurge = 9, + kStatMarker = 10, + kStatTraps = 11, + kStatAmbience = 12, + kStatSpares = 13, + kStatFlare = 14, + kStatDebris = 15, + kStatPathMarker = 16, + kStatFree = 1024, }; // POWERUPS ///////////////////////////////////////////////////// enum { -kPwUpFeatherFall = 12, -kPwUpShadowCloak = 13, -kPwUpDeathMask = 14, -kPwUpJumpBoots = 15, -kPwUpTwoGuns = 17, -kPwUpDivingSuit = 18, -kPwUpGasMask = 19, -kPwUpCrystalBall = 21, -kPwUpDoppleganger = 23, -kPwUpReflectShots = 24, -kPwUpBeastVision = 25, -kPwUpShadowCloakUseless = 26, -kPwUpDeliriumShroom = 28, -kPwUpGrowShroom = 29, -kPwUpShrinkShroom = 30, -kPwUpDeathMaskUseless = 31, -kPwUpAsbestArmor = 39, -kMaxPowerUps = 51, + kPwUpFeatherFall = 12, + kPwUpShadowCloak = 13, + kPwUpDeathMask = 14, + kPwUpJumpBoots = 15, + kPwUpTwoGuns = 17, + kPwUpDivingSuit = 18, + kPwUpGasMask = 19, + kPwUpCrystalBall = 21, + kPwUpDoppleganger = 23, + kPwUpReflectShots = 24, + kPwUpBeastVision = 25, + kPwUpShadowCloakUseless = 26, + kPwUpDeliriumShroom = 28, + kPwUpGrowShroom = 29, + kPwUpShrinkShroom = 30, + kPwUpDeathMaskUseless = 31, + kPwUpAsbestArmor = 39, + kMaxPowerUps = 51, }; enum { - kExplosionSmall = 0, - kExplosionStandard = 1, - kExplosionLarge = 2, - kExplosionFireball = 3, - kExplosionSpray = 4, - kExplosion5 = 5, - kExplosion6 = 6, - kExplosionNapalm = 7, - kExplosionMax = 8 + kExplosionSmall = 0, + kExplosionStandard = 1, + kExplosionLarge = 2, + kExplosionFireball = 3, + kExplosionSpray = 4, + kExplosion5 = 5, + kExplosion6 = 6, + kExplosionNapalm = 7, + kExplosionMax = 8 }; // SPRITE TYPES ///////////////////////////////////////////////// enum { - kSpriteDecoration = 0, + kSpriteDecoration = 0, - // markers - kMarkerSPStart = 1, - kMarkerMPStart = 2, - kMarkerOff = 3, - kMarkerOn = 4, - kMarkerAxis = 5, - kMarkerLowLink = 6, - kMarkerUpLink = 7, - kMarkerWarpDest = 8, - kMarkerUpWater = 9, - kMarkerLowWater = 10, - kMarkerUpStack = 11, - kMarkerLowStack = 12, - kMarkerUpGoo = 13, - kMarkerLowGoo = 14, - kMarkerPath = 15, - kMarkerDudeSpawn = 18, - kMarkerEarthQuake = 19, + // markers + kMarkerSPStart = 1, + kMarkerMPStart = 2, + kMarkerOff = 3, + kMarkerOn = 4, + kMarkerAxis = 5, + kMarkerLowLink = 6, + kMarkerUpLink = 7, + kMarkerWarpDest = 8, + kMarkerUpWater = 9, + kMarkerLowWater = 10, + kMarkerUpStack = 11, + kMarkerLowStack = 12, + kMarkerUpGoo = 13, + kMarkerLowGoo = 14, + kMarkerPath = 15, + kMarkerDudeSpawn = 18, + kMarkerEarthQuake = 19, - // switches - kSwitchBase = 20, - kSwitchToggle = 20, - kSwitchOneWay = 21, - kSwitchCombo = 22, - kSwitchPadlock = 23, - kSwitchMax = 24, + // switches + kSwitchBase = 20, + kSwitchToggle = 20, + kSwitchOneWay = 21, + kSwitchCombo = 22, + kSwitchPadlock = 23, + kSwitchMax = 24, - // decorations - kDecorationTorch = 30, - kDecorationCandle = 32, + // decorations + kDecorationTorch = 30, + kDecorationCandle = 32, - // (weapons) - kItemWeaponBase = 40, - kItemWeaponRandom = kItemWeaponBase, - kItemWeaponSawedoff = 41, - kItemWeaponTommygun = 42, - kItemWeaponFlarePistol = 43, - kItemWeaponVoodooDoll = 44, - kItemWeaponTeslaCannon = 45, - kItemWeaponNapalmLauncher = 46, - kItemWeaponPitchfork = 47, - kItemWeaponSprayCan = 48, - kItemWeaponTNT = 49, - kItemWeaponLifeLeech = 50, - kItemWeaponMax = 51, + // (weapons) + kItemWeaponBase = 40, + kItemWeaponRandom = kItemWeaponBase, + kItemWeaponSawedoff = 41, + kItemWeaponTommygun = 42, + kItemWeaponFlarePistol = 43, + kItemWeaponVoodooDoll = 44, + kItemWeaponTeslaCannon = 45, + kItemWeaponNapalmLauncher = 46, + kItemWeaponPitchfork = 47, + kItemWeaponSprayCan = 48, + kItemWeaponTNT = 49, + kItemWeaponLifeLeech = 50, + kItemWeaponMax = 51, - // items (ammos) - kItemAmmoBase = 60, - kItemAmmoSprayCan = kItemAmmoBase, - kItemAmmoTNTBundle = 62, - kItemAmmoTNTBox = 63, - kItemAmmoProxBombBundle = 64, - kItemAmmoRemoteBombBundle = 65, - kItemAmmoTrappedSoul = 66, - kItemAmmoSawedoffFew = 67, - kItemAmmoSawedoffBox = 68, - kItemAmmoTommygunFew = 69, - kItemAmmoVoodooDoll = 70, - kItemAmmoTommygunDrum = 72, - kItemAmmoTeslaCharge = 73, - kItemAmmoFlares = 76, - kItemAmmoGasolineCan = 79, - kItemAmmoMax = 81, + // items (ammos) + kItemAmmoBase = 60, + kItemAmmoSprayCan = kItemAmmoBase, + kItemAmmoTNTBundle = 62, + kItemAmmoTNTBox = 63, + kItemAmmoProxBombBundle = 64, + kItemAmmoRemoteBombBundle = 65, + kItemAmmoTrappedSoul = 66, + kItemAmmoSawedoffFew = 67, + kItemAmmoSawedoffBox = 68, + kItemAmmoTommygunFew = 69, + kItemAmmoVoodooDoll = 70, + kItemAmmoTommygunDrum = 72, + kItemAmmoTeslaCharge = 73, + kItemAmmoFlares = 76, + kItemAmmoGasolineCan = 79, + kItemAmmoMax = 81, - kItemBase = 100, - - // items (keys) - kItemKeyBase = kItemBase, - kItemKeySkull = kItemKeyBase, - kItemKeyEye = 101, - kItemKeyFire = 102, - kItemKeyDagger = 103, - kItemKeySpider = 104, - kItemKeyMoon = 105, - kItemKeyKey7 = 106, - kItemKeyMax = 107, + kItemBase = 100, - // items (health) - kItemHealthDoctorBag = 107, - kItemHealthMedPouch = 108, - kItemHealthLifeEssense = 109, - kItemHealthLifeSeed = 110, - kItemHealthRedPotion = 111, + // items (keys) + kItemKeyBase = kItemBase, + kItemKeySkull = kItemKeyBase, + kItemKeyEye = 101, + kItemKeyFire = 102, + kItemKeyDagger = 103, + kItemKeySpider = 104, + kItemKeyMoon = 105, + kItemKeyKey7 = 106, + kItemKeyMax = 107, - // items (misc) - kItemFeatherFall = 112, - kItemShadowCloak = 113, // ltdInvisibility - kItemDeathMask = 114, // invulnerability - kItemJumpBoots = 115, - kItemTwoGuns = 117, - kItemDivingSuit = 118, - kItemGasMask = 119, - kItemCrystalBall = 121, - kItemReflectShots = 124, - kItemBeastVision = 125, - kItemShroomDelirium = 128, + // items (health) + kItemHealthDoctorBag = 107, + kItemHealthMedPouch = 108, + kItemHealthLifeEssense = 109, + kItemHealthLifeSeed = 110, + kItemHealthRedPotion = 111, - kItemArmorAsbest = 139, - kItemArmorBasic = 140, - kItemArmorBody = 141, - kItemArmorFire = 142, - kItemArmorSpirit = 143, - kItemArmorSuper = 144, + // items (misc) + kItemFeatherFall = 112, + kItemShadowCloak = 113, // ltdInvisibility + kItemDeathMask = 114, // invulnerability + kItemJumpBoots = 115, + kItemTwoGuns = 117, + kItemDivingSuit = 118, + kItemGasMask = 119, + kItemCrystalBall = 121, + kItemReflectShots = 124, + kItemBeastVision = 125, + kItemShroomDelirium = 128, - kItemFlagABase = 145, - kItemFlagBBase = 146, - kItemFlagA = 147, - kItemFlagB = 148, - kItemMax = 151, + kItemArmorAsbest = 139, + kItemArmorBasic = 140, + kItemArmorBody = 141, + kItemArmorFire = 142, + kItemArmorSpirit = 143, + kItemArmorSuper = 144, - // dudes - kDudeBase = 200, - kDudeCultistTommy = 201, - kDudeCultistShotgun = 202, - kDudeZombieAxeNormal = 203, - kDudeZombieButcher = 204, - kDudeZombieAxeBuried = 205, - kDudeGargoyleFlesh = 206, - kDudeGargoyleStone = 207, - kDudeGargoyleStatueFlesh = 208, - kDudeGargoyleStatueStone = 209, - kDudePhantasm = 210, - kDudeHellHound = 211, - kDudeHand = 212, - kDudeSpiderBrown = 213, - kDudeSpiderRed = 214, - kDudeSpiderBlack = 215, - kDudeSpiderMother = 216, - kDudeGillBeast = 217, - kDudeBoneEel = 218, - kDudeBat = 219, - kDudeRat = 220, - kDudePodGreen = 221, - kDudeTentacleGreen = 222, - kDudePodFire = 223, - kDudeTentacleFire = 224, - kDudePodMother = 225, - kDudeTentacleMother = 226, - kDudeCerberusTwoHead = 227, - kDudeCerberusOneHead = 228, - kDudeTchernobog = 229, - kDudeCultistTommyProne = 230, - kDudePlayer1 = 231, - kDudePlayer2 = 232, - kDudePlayer3 = 233, - kDudePlayer4 = 234, - kDudePlayer5 = 235, - kDudePlayer6 = 236, - kDudePlayer7 = 237, - kDudePlayer8 = 238, - kDudeBurningInnocent = 239, - kDudeBurningCultist = 240, - kDudeBurningZombieAxe = 241, - kDudeBurningZombieButcher = 242, - kDudeCultistReserved = 243, // unused - kDudeZombieAxeLaying = 244, - kDudeInnocent = 245, - kDudeCultistShotgunProne = 246, - kDudeCultistTesla = 247, - kDudeCultistTNT = 248, - kDudeCultistBeast = 249, - kDudeTinyCaleb = 250, - kDudeBeast = 251, - kDudeBurningTinyCaleb = 252, - kDudeBurningBeast = 253, - kDudeVanillaMax = 254, - kDudeMax = 256, - - kMissileBase = 300, - kMissileButcherKnife = kMissileBase, - kMissileFlareRegular = 301, - kMissileTeslaAlt = 302, - kMissileFlareAlt = 303, - kMissileFlameSpray = 304, - kMissileFireball = 305, - kMissileTeslaRegular = 306, - kMissileEctoSkull = 307, - kMissileFlameHound = 308, - kMissilePukeGreen = 309, - kMissileUnused = 310, - kMissileArcGargoyle = 311, - kMissileFireballNapalm = 312, - kMissileFireballCerberus = 313, - kMissileFireballTchernobog = 314, - kMissileLifeLeechRegular = 315, - kMissileLifeLeechAltNormal = 316, - kMissileLifeLeechAltSmall = 317, - kMissileMax = 318, + kItemFlagABase = 145, + kItemFlagBBase = 146, + kItemFlagA = 147, + kItemFlagB = 148, + kItemMax = 151, - // things - kThingBase = 400, - kThingTNTBarrel = 400, - kThingArmedProxBomb = 401, - kThingArmedRemoteBomb = 402, - kThingCrateFace = 405, - kThingGlassWindow = 406, - kThingFluorescent = 407, - kThingWallCrack = 408, - kThingSpiderWeb = 410, - kThingMetalGrate = 411, - kThingFlammableTree = 412, - kTrapMachinegun = 413, // not really a thing, should be in traps instead - kThingFallingRock = 414, - kThingKickablePail = 415, - kThingObjectGib = 416, - kThingObjectExplode = 417, - kThingArmedTNTStick = 418, - kThingArmedTNTBundle = 419, - kThingArmedSpray = 420, - kThingBone = 421, - kThingDripWater = 423, - kThingDripBlood = 424, - kThingBloodBits = 425, - kThingBloodChunks = 426, - kThingZombieHead = 427, - kThingNapalmBall = 428, - kThingPodFireBall = 429, - kThingPodGreenBall = 430, - kThingDroppedLifeLeech = 431, - kThingVoodooHead = 432, // unused - kThingMax = 436, + // dudes + kDudeBase = 200, + kDudeCultistTommy = 201, + kDudeCultistShotgun = 202, + kDudeZombieAxeNormal = 203, + kDudeZombieButcher = 204, + kDudeZombieAxeBuried = 205, + kDudeGargoyleFlesh = 206, + kDudeGargoyleStone = 207, + kDudeGargoyleStatueFlesh = 208, + kDudeGargoyleStatueStone = 209, + kDudePhantasm = 210, + kDudeHellHound = 211, + kDudeHand = 212, + kDudeSpiderBrown = 213, + kDudeSpiderRed = 214, + kDudeSpiderBlack = 215, + kDudeSpiderMother = 216, + kDudeGillBeast = 217, + kDudeBoneEel = 218, + kDudeBat = 219, + kDudeRat = 220, + kDudePodGreen = 221, + kDudeTentacleGreen = 222, + kDudePodFire = 223, + kDudeTentacleFire = 224, + kDudePodMother = 225, + kDudeTentacleMother = 226, + kDudeCerberusTwoHead = 227, + kDudeCerberusOneHead = 228, + kDudeTchernobog = 229, + kDudeCultistTommyProne = 230, + kDudePlayer1 = 231, + kDudePlayer2 = 232, + kDudePlayer3 = 233, + kDudePlayer4 = 234, + kDudePlayer5 = 235, + kDudePlayer6 = 236, + kDudePlayer7 = 237, + kDudePlayer8 = 238, + kDudeBurningInnocent = 239, + kDudeBurningCultist = 240, + kDudeBurningZombieAxe = 241, + kDudeBurningZombieButcher = 242, + kDudeCultistReserved = 243, // unused + kDudeZombieAxeLaying = 244, + kDudeInnocent = 245, + kDudeCultistShotgunProne = 246, + kDudeCultistTesla = 247, + kDudeCultistTNT = 248, + kDudeCultistBeast = 249, + kDudeTinyCaleb = 250, + kDudeBeast = 251, + kDudeBurningTinyCaleb = 252, + kDudeBurningBeast = 253, + kDudeVanillaMax = 254, + kDudeMax = 256, - // traps - kTrapFlame = 452, - kTrapSawCircular = 454, - kTrapZapSwitchable = 456, - kTrapExploder = 459, + kMissileBase = 300, + kMissileButcherKnife = kMissileBase, + kMissileFlareRegular = 301, + kMissileTeslaAlt = 302, + kMissileFlareAlt = 303, + kMissileFlameSpray = 304, + kMissileFireball = 305, + kMissileTeslaRegular = 306, + kMissileEctoSkull = 307, + kMissileFlameHound = 308, + kMissilePukeGreen = 309, + kMissileUnused = 310, + kMissileArcGargoyle = 311, + kMissileFireballNapalm = 312, + kMissileFireballCerberus = 313, + kMissileFireballTchernobog = 314, + kMissileLifeLeechRegular = 315, + kMissileLifeLeechAltNormal = 316, + kMissileLifeLeechAltSmall = 317, + kMissileMax = 318, - // generators - kGenTrigger = 700, - kGenDripWater = 701, - kGenDripBlood = 702, - kGenMissileFireball = 703, - kGenMissileEctoSkull = 704, - kGenDart = 705, - kGenBubble = 706, - kGenBubbleMulti = 707, - - // sound sprites - kGenSound = 708, - kSoundSector = 709, - kSoundPlayer = 711, + // things + kThingBase = 400, + kThingTNTBarrel = 400, + kThingArmedProxBomb = 401, + kThingArmedRemoteBomb = 402, + kThingCrateFace = 405, + kThingGlassWindow = 406, + kThingFluorescent = 407, + kThingWallCrack = 408, + kThingSpiderWeb = 410, + kThingMetalGrate = 411, + kThingFlammableTree = 412, + kTrapMachinegun = 413, // not really a thing, should be in traps instead + kThingFallingRock = 414, + kThingKickablePail = 415, + kThingObjectGib = 416, + kThingObjectExplode = 417, + kThingArmedTNTStick = 418, + kThingArmedTNTBundle = 419, + kThingArmedSpray = 420, + kThingBone = 421, + kThingDripWater = 423, + kThingDripBlood = 424, + kThingBloodBits = 425, + kThingBloodChunks = 426, + kThingZombieHead = 427, + kThingNapalmBall = 428, + kThingPodFireBall = 429, + kThingPodGreenBall = 430, + kThingDroppedLifeLeech = 431, + kThingVoodooHead = 432, // unused + kThingMax = 436, + + // traps + kTrapFlame = 452, + kTrapSawCircular = 454, + kTrapZapSwitchable = 456, + kTrapExploder = 459, + + // generators + kGenTrigger = 700, + kGenDripWater = 701, + kGenDripBlood = 702, + kGenMissileFireball = 703, + kGenMissileEctoSkull = 704, + kGenDart = 705, + kGenBubble = 706, + kGenBubbleMulti = 707, + + // sound sprites + kGenSound = 708, + kSoundSector = 709, + kSoundPlayer = 711, }; // WALL TYPES ///////////////////////////////////////////////// enum { - kWallBase = 500, - kWallStack = 501, - kWallGib = 511, - kWallMax = 512, + kWallBase = 500, + kWallStack = 501, + kWallGib = 511, + kWallMax = 512, }; // SECTOR TYPES ///////////////////////////////////////////////// enum { - kSectorBase = 600, - kSectorZMotion = 600, - kSectorZMotionSprite = 602, - kSectorTeleport = 604, - kSectorPath = 612, - kSectorRotateStep = 613, - kSectorSlideMarked = 614, - kSectorRotateMarked = 615, - kSectorSlide = 616, - kSectorRotate = 617, - kSectorDamage = 618, - kSectorCounter = 619, - kSectorMax = 620, + kSectorBase = 600, + kSectorZMotion = 600, + kSectorZMotionSprite = 602, + kSectorTeleport = 604, + kSectorPath = 612, + kSectorRotateStep = 613, + kSectorSlideMarked = 614, + kSectorRotateMarked = 615, + kSectorSlide = 616, + kSectorRotate = 617, + kSectorDamage = 618, + kSectorCounter = 619, + kSectorMax = 620, }; // ai state types enum { -kAiStateOther = -1, -kAiStateIdle = 0, -kAiStateGenIdle = 1, -kAiStateMove = 2, -kAiStateSearch = 3, -kAiStateChase = 4, -kAiStateRecoil = 5, -kAiStateAttack = 6, -kAiStatePatrolBase = 7, -kAiStatePatrolWaitL = kAiStatePatrolBase, -kAiStatePatrolWaitC, -kAiStatePatrolWaitW, -kAiStatePatrolMoveL, -kAiStatePatrolMoveC, -kAiStatePatrolMoveW, -kAiStatePatrolTurnL, -kAiStatePatrolTurnC, -kAiStatePatrolTurnW, -kAiStatePatrolMax, + kAiStateOther = -1, + kAiStateIdle = 0, + kAiStateGenIdle = 1, + kAiStateMove = 2, + kAiStateSearch = 3, + kAiStateChase = 4, + kAiStateRecoil = 5, + kAiStateAttack = 6, + kAiStatePatrolBase = 7, + kAiStatePatrolWaitL = kAiStatePatrolBase, + kAiStatePatrolWaitC, + kAiStatePatrolWaitW, + kAiStatePatrolMoveL, + kAiStatePatrolMoveC, + kAiStatePatrolMoveW, + kAiStatePatrolTurnL, + kAiStatePatrolTurnC, + kAiStatePatrolTurnW, + kAiStatePatrolMax, }; enum { - // sprite attributes - kHitagAutoAim = 0x0008, - kHitagRespawn = 0x0010, - kHitagFree = 0x0020, - kHitagSmoke = 0x0100, + // sprite attributes + kHitagAutoAim = 0x0008, + kHitagRespawn = 0x0010, + kHitagFree = 0x0020, + kHitagSmoke = 0x0100, - // sprite physics attributes - kPhysMove = 0x0001, // affected by movement physics - kPhysGravity = 0x0002, // affected by gravity - kPhysFalling = 0x0004, // currently in z-motion + // sprite physics attributes + kPhysMove = 0x0001, // affected by movement physics + kPhysGravity = 0x0002, // affected by gravity + kPhysFalling = 0x0004, // currently in z-motion - // sector cstat - kSecCParallax = 0x01, - kSecCSloped = 0x02, - kSecCSwapXY = 0x04, - kSecCExpand = 0x08, - kSecCFlipX = 0x10, - kSecCFlipY = 0x20, - kSecCFlipMask = 0x34, - kSecCRelAlign = 0x40, - kSecCFloorShade = 0x8000, + // sector cstat + kSecCParallax = 0x01, + kSecCSloped = 0x02, + kSecCSwapXY = 0x04, + kSecCExpand = 0x08, + kSecCFlipX = 0x10, + kSecCFlipY = 0x20, + kSecCFlipMask = 0x34, + kSecCRelAlign = 0x40, + kSecCFloorShade = 0x8000, - kAng5 = 28, - kAng15 = 85, - kAng30 = 170, - kAng45 = 256, - kAng60 = 341, - kAng90 = 512, - kAng120 = 682, - kAng180 = 1024, - kAng360 = 2048, + kAng5 = 28, + kAng15 = 85, + kAng30 = 170, + kAng45 = 256, + kAng60 = 341, + kAng90 = 512, + kAng120 = 682, + kAng180 = 1024, + kAng360 = 2048, }; // Weapon numbers enum { - kWeapNone = 0, - kWeapPitchFork = 1, - kWeapFlareGun = 2, - kWeapShotgun = 3, - kWeapTommyGun = 4, - kWeapNapalm = 5, - kWeapDynamite = 6, - kWeapSpraycan = 7, - kWeapTeslaCannon = 8, - kWeapLifeLeech = 9, - kWeapVoodooDoll = 10, - kWeapProximity = 11, - kWeapRemote = 12, - kWeapBeast = 13, + kWeapNone = 0, + kWeapPitchFork = 1, + kWeapFlareGun = 2, + kWeapShotgun = 3, + kWeapTommyGun = 4, + kWeapNapalm = 5, + kWeapDynamite = 6, + kWeapSpraycan = 7, + kWeapTeslaCannon = 8, + kWeapLifeLeech = 9, + kWeapVoodooDoll = 10, + kWeapProximity = 11, + kWeapRemote = 12, + kWeapBeast = 13, }; // ------------------------------- @@ -490,95 +490,95 @@ enum #pragma pack(push,1) struct LOCATION { - int x, y, z; - int ang; + int x, y, z; + int ang; }; using POINT2D = vec2_t; using POINT3D = vec3_t; struct VECTOR2D { - int dx, dy; + int dx, dy; }; struct Aim { - int dx, dy, dz; + int dx, dy, dz; }; #pragma pack(pop) inline int ClipLow(int a, int b) { - if (a < b) - return b; - return a; + if (a < b) + return b; + return a; } inline int ClipHigh(int a, int b) { - if (a >= b) - return b; - return a; + if (a >= b) + return b; + return a; } inline int ClipRange(int a, int b, int c) { - if (a < b) - return b; - if (a > c) - return c; - return a; + if (a < b) + return b; + if (a > c) + return c; + return a; } inline uint8_t Chance(int a1) { - return wrand() < (a1>>1); + return wrand() < (a1 >> 1); } inline unsigned int Random(int a1) { - return MulScale(wrand(), a1, 15); + return MulScale(wrand(), a1, 15); } inline int Random2(int a1) { - return MulScale(wrand(), a1, 14)-a1; + return MulScale(wrand(), a1, 14) - a1; } inline int Random3(int a1) { - return MulScale(wrand()+wrand(), a1, 15) - a1; + return MulScale(wrand() + wrand(), a1, 15) - a1; } inline unsigned int QRandom(int a1) { - return MulScale(qrand(), a1, 15); + return MulScale(qrand(), a1, 15); } inline int QRandom2(int a1) { - return MulScale(qrand(), a1, 14)-a1; + return MulScale(qrand(), a1, 14) - a1; } template -inline void SetBitString(T *pArray, int nIndex) +inline void SetBitString(T* pArray, int nIndex) { static_assert(sizeof(T) == 1, "Bit array element too large"); - pArray[nIndex>>3] |= 1<<(nIndex&7); + pArray[nIndex >> 3] |= 1 << (nIndex & 7); } template -inline void ClearBitString(T *pArray, int nIndex) +inline void ClearBitString(T* pArray, int nIndex) { static_assert(sizeof(T) == 1, "Bit array element too large"); pArray[nIndex >> 3] &= ~(1 << (nIndex & 7)); } template -inline bool TestBitString(T *pArray, int nIndex) +inline bool TestBitString(T* pArray, int nIndex) { static_assert(sizeof(T) == 1, "Bit array element too large"); - return !!(pArray[nIndex>>3] & (1<<(nIndex&7))); + return !!(pArray[nIndex >> 3] & (1 << (nIndex & 7))); } // This is to override the namepace prioritization without altering the actual calls. @@ -589,145 +589,145 @@ inline int scale(int a, int b, int c) inline int scale(int a1, int a2, int a3, int a4, int a5) { - return a4 + (a5-a4) * (a1-a2) / (a3-a2); + return a4 + (a5 - a4) * (a1 - a2) / (a3 - a2); } inline int mulscale16r(int a, int b) { - int64_t acc = 1<<(16-1); - acc += ((int64_t)a) * b; - return (int)(acc>>16); + int64_t acc = 1 << (16 - 1); + acc += ((int64_t)a) * b; + return (int)(acc >> 16); } inline int mulscale30r(int a, int b) { - int64_t acc = 1<<(30-1); - acc += ((int64_t)a) * b; - return (int)(acc>>30); + int64_t acc = 1 << (30 - 1); + acc += ((int64_t)a) * b; + return (int)(acc >> 30); } inline int dmulscale30r(int a, int b, int c, int d) { - int64_t acc = 1<<(30-1); - acc += ((int64_t)a) * b; - acc += ((int64_t)c) * d; - return (int)(acc>>30); + int64_t acc = 1 << (30 - 1); + acc += ((int64_t)a) * b; + acc += ((int64_t)c) * d; + return (int)(acc >> 30); } inline int approxDist(int dx, int dy) { - dx = abs(dx); - dy = abs(dy); - if (dx > dy) - dy = (3*dy)>>3; - else - dx = (3*dx)>>3; - return dx+dy; + dx = abs(dx); + dy = abs(dy); + if (dx > dy) + dy = (3 * dy) >> 3; + else + dx = (3 * dx) >> 3; + return dx + dy; } class Rect { public: - int x0, y0, x1, y1; - Rect(int _x0, int _y0, int _x1, int _y1) - { - x0 = _x0; y0 = _y0; x1 = _x1; y1 = _y1; - } - bool isValid(void) const - { - return x0 < x1 && y0 < y1; - } - bool isEmpty(void) const - { - return !isValid(); - } - bool operator!(void) const - { - return isEmpty(); - } + int x0, y0, x1, y1; + Rect(int _x0, int _y0, int _x1, int _y1) + { + x0 = _x0; y0 = _y0; x1 = _x1; y1 = _y1; + } + bool isValid(void) const + { + return x0 < x1&& y0 < y1; + } + bool isEmpty(void) const + { + return !isValid(); + } + bool operator!(void) const + { + return isEmpty(); + } - Rect & operator&=(Rect &pOther) - { - x0 = ClipLow(x0, pOther.x0); - y0 = ClipLow(y0, pOther.y0); - x1 = ClipHigh(x1, pOther.x1); - y1 = ClipHigh(y1, pOther.y1); - return *this; - } + Rect& operator&=(Rect& pOther) + { + x0 = ClipLow(x0, pOther.x0); + y0 = ClipLow(y0, pOther.y0); + x1 = ClipHigh(x1, pOther.x1); + y1 = ClipHigh(y1, pOther.y1); + return *this; + } - void offset(int dx, int dy) - { - x0 += dx; - y0 += dy; - x1 += dx; - y1 += dy; - } + void offset(int dx, int dy) + { + x0 += dx; + y0 += dy; + x1 += dx; + y1 += dy; + } - int height() - { - return y1 - y0; - } + int height() + { + return y1 - y0; + } - int width() - { - return x1 - x0; - } + int width() + { + return x1 - x0; + } - bool inside(Rect& other) - { - return (x0 <= other.x0 && x1 >= other.x1 && y0 <= other.y0 && y1 >= other.y1); - } + bool inside(Rect& other) + { + return (x0 <= other.x0 && x1 >= other.x1 && y0 <= other.y0 && y1 >= other.y1); + } - bool inside(int x, int y) - { - return (x0 <= x && x1 > x && y0 <= y && y1 > y); - } + bool inside(int x, int y) + { + return (x0 <= x && x1 > x && y0 <= y && y1 > y); + } }; class BitReader { public: - int nBitPos; - int nSize; - char *pBuffer; - BitReader(char *_pBuffer, int _nSize, int _nBitPos) { pBuffer = _pBuffer; nSize = _nSize; nBitPos = _nBitPos; nSize -= nBitPos>>3; } - BitReader(char *_pBuffer, int _nSize) { pBuffer = _pBuffer; nSize = _nSize; nBitPos = 0; } - int readBit() - { - if (nSize <= 0) - I_Error("Buffer overflow in BitReader"); - int bit = ((*pBuffer)>>nBitPos)&1; - if (++nBitPos >= 8) - { - nBitPos = 0; - pBuffer++; - nSize--; - } - return bit; - } - void skipBits(int nBits) - { - nBitPos += nBits; - pBuffer += nBitPos>>3; - nSize -= nBitPos>>3; - nBitPos &= 7; - if ((nSize == 0 && nBitPos > 0) || nSize < 0) - I_Error("Buffer overflow in BitReader"); - } - unsigned int readUnsigned(int nBits) - { - unsigned int n = 0; - assert(nBits <= 32); - for (int i = 0; i < nBits; i++) - n += readBit()<>= 32-nBits; - return n; - } + int nBitPos; + int nSize; + char* pBuffer; + BitReader(char* _pBuffer, int _nSize, int _nBitPos) { pBuffer = _pBuffer; nSize = _nSize; nBitPos = _nBitPos; nSize -= nBitPos >> 3; } + BitReader(char* _pBuffer, int _nSize) { pBuffer = _pBuffer; nSize = _nSize; nBitPos = 0; } + int readBit() + { + if (nSize <= 0) + I_Error("Buffer overflow in BitReader"); + int bit = ((*pBuffer) >> nBitPos) & 1; + if (++nBitPos >= 8) + { + nBitPos = 0; + pBuffer++; + nSize--; + } + return bit; + } + void skipBits(int nBits) + { + nBitPos += nBits; + pBuffer += nBitPos >> 3; + nSize -= nBitPos >> 3; + nBitPos &= 7; + if ((nSize == 0 && nBitPos > 0) || nSize < 0) + I_Error("Buffer overflow in BitReader"); + } + unsigned int readUnsigned(int nBits) + { + unsigned int n = 0; + assert(nBits <= 32); + for (int i = 0; i < nBits; i++) + n += readBit() << i; + return n; + } + int readSigned(int nBits) + { + assert(nBits <= 32); + int n = (int)readUnsigned(nBits); + n <<= 32 - nBits; + n >>= 32 - nBits; + return n; + } }; diff --git a/source/games/blood/src/controls.cpp b/source/games/blood/src/controls.cpp index 79bf7d13a..1c48cd0b7 100644 --- a/source/games/blood/src/controls.cpp +++ b/source/games/blood/src/controls.cpp @@ -37,40 +37,46 @@ static InputPacket gInput; void UpdatePlayerSpriteAngle(PLAYER* pPlayer); void doslopetilting(PLAYER* pPlayer, double const scaleAdjust); +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void GameInterface::GetInput(ControlInfo* const hidInput, double const scaleAdjust, InputPacket* packet) { - if (paused || M_Active()) - { - gInput = {}; - return; - } + if (paused || M_Active()) + { + gInput = {}; + return; + } - PLAYER* pPlayer = &gPlayer[myconnectindex]; - InputPacket input {}; + PLAYER* pPlayer = &gPlayer[myconnectindex]; + InputPacket input{}; - ApplyGlobalInput(gInput, hidInput); - processMovement(&input, &gInput, hidInput, scaleAdjust); + ApplyGlobalInput(gInput, hidInput); + processMovement(&input, &gInput, hidInput, scaleAdjust); - if (!SyncInput() && gamestate == GS_LEVEL) - { - // Perform unsynchronised angle/horizon if not dead. - if (gView->actor->xspr.health != 0) - { - pPlayer->angle.applyinput(input.avel, &pPlayer->input.actions, scaleAdjust); - pPlayer->horizon.applyinput(input.horz, &pPlayer->input.actions, scaleAdjust); - doslopetilting(pPlayer, scaleAdjust); - } + if (!SyncInput() && gamestate == GS_LEVEL) + { + // Perform unsynchronised angle/horizon if not dead. + if (gView->actor->xspr.health != 0) + { + pPlayer->angle.applyinput(input.avel, &pPlayer->input.actions, scaleAdjust); + pPlayer->horizon.applyinput(input.horz, &pPlayer->input.actions, scaleAdjust); + doslopetilting(pPlayer, scaleAdjust); + } - pPlayer->angle.processhelpers(scaleAdjust); - pPlayer->horizon.processhelpers(scaleAdjust); - UpdatePlayerSpriteAngle(pPlayer); - } + pPlayer->angle.processhelpers(scaleAdjust); + pPlayer->horizon.processhelpers(scaleAdjust); + UpdatePlayerSpriteAngle(pPlayer); + } - if (packet) - { - *packet = gInput; - gInput = {}; - } + if (packet) + { + *packet = gInput; + gInput = {}; + } } //--------------------------------------------------------------------------- @@ -81,7 +87,7 @@ void GameInterface::GetInput(ControlInfo* const hidInput, double const scaleAdju void GameInterface::clearlocalinputstate() { - gInput = {}; + gInput = {}; } END_BLD_NS diff --git a/source/games/blood/src/d_menu.cpp b/source/games/blood/src/d_menu.cpp index 3eb128f00..b75da2a1d 100644 --- a/source/games/blood/src/d_menu.cpp +++ b/source/games/blood/src/d_menu.cpp @@ -49,6 +49,12 @@ public: void Draw(void); }; +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + CGameMenuItemQAV::CGameMenuItemQAV(int a3, int a4, const char* name, bool widescreen, bool clearbackground) { bWideScreen = widescreen; @@ -67,6 +73,12 @@ CGameMenuItemQAV::CGameMenuItemQAV(int a3, int a4, const char* name, bool widesc } } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void CGameMenuItemQAV::Draw(void) { if (bClearBackground) @@ -103,6 +115,12 @@ void CGameMenuItemQAV::Draw(void) } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + static std::unique_ptr itemBloodQAV; // This must be global to ensure that the animation remains consistent across menus. void UpdateNetworkMenus(void)