Skip to content
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
f4b9881
Add new Helper function PrintMessage
ChrisLv-CN Aug 8, 2023
c39099e
Add ini file name getter
ChrisLv-CN Aug 12, 2023
f9ebe17
重载等于运算符,支持多类型转换
ChrisLv-CN Sep 8, 2023
61efafb
增加非模板类型的操作函数
ChrisLv-CN Sep 8, 2023
4b21ce9
Add ColorStruct helper
ChrisLv-CN Sep 9, 2023
46738a5
add GetSpeed function
ChrisLv-CN Sep 9, 2023
6493db2
add some helper
ChrisLv-CN Sep 9, 2023
f3bd2ff
fix TechnoClass::GetFacing use wrong type.
ChrisLv-CN Sep 9, 2023
6754259
add draw bolt function
ChrisLv-CN Sep 9, 2023
3f4f5eb
forward declarations
ChrisLv-CN Sep 9, 2023
e95611e
add TileType for helper
ChrisLv-CN Sep 18, 2023
bb80345
add GetTileType for helper
ChrisLv-CN Sep 19, 2023
f8ea778
add DrawText and DrawSHP for helper
ChrisLv-CN Sep 21, 2023
6a0da40
add Color::Yellow
ChrisLv-CN Sep 22, 2023
709bf9d
add new item for drawing
ChrisLv-CN Sep 23, 2023
7630681
add FindSuperWeapon for helper but not useful
ChrisLv-CN Sep 24, 2023
015c65e
add InRange check and Fire_IgnoreType for Helper
ChrisLv-CN Sep 28, 2023
af85d84
change DiskLaserTimer to ROFTimer
ChrisLv-CN Sep 29, 2023
9793fcb
add more helper func
ChrisLv-CN Sep 29, 2023
4931481
change CellClass* to AbstractClass* for homing
ChrisLv-CN Oct 1, 2023
bdd2193
change name for homing
ChrisLv-CN Oct 1, 2023
8ff705f
TechnoTypeClass::MaxDebris and MinDebris is wrong.
ChrisLv-CN Oct 9, 2023
6a7ccac
add Include <ArrayClasses.h> to EBolt.h
ChrisLv-CN Feb 4, 2024
0c1798d
BuildingClass->BState type change to BStateType
ChrisLv-CN Feb 11, 2024
76eda83
Add Walk and Mech Loco
ChrisLv-CN Feb 15, 2024
690a7c0
PointerGotInvalid rename to Detach
ChrisLv-CN Feb 16, 2024
08bcef4
rename
ChrisLv-CN Feb 25, 2024
6bbaa01
add function Direction(pTarget)
ChrisLv-CN Mar 3, 2024
78531b1
rename unknown_bool_432 to WasSelected
ChrisLv-CN Mar 6, 2024
70f854d
add DrawLineBlit function to draw Boris's target laser
ChrisLv-CN Mar 10, 2024
eea4966
add function
ChrisLv-CN Mar 11, 2024
e2dd825
bugfix, wrong param
ChrisLv-CN Mar 15, 2024
629df44
Add AircraftTrackerClass for searching Techno in air
ChrisLv-CN Mar 17, 2024
b1134e3
rename
ChrisLv-CN Mar 18, 2024
6119e87
add function
ChrisLv-CN Mar 23, 2024
dc04da1
add function
ChrisLv-CN Mar 24, 2024
9e75ed4
add function
ChrisLv-CN Mar 25, 2024
70dd0be
add Helper function
ChrisLv-CN Mar 26, 2024
9694f78
typechange
ChrisLv-CN Mar 26, 2024
36aee93
bugfix
ChrisLv-CN Mar 26, 2024
70ffa73
rename
ChrisLv-CN Mar 29, 2024
fcf7341
KamikazeControl的目标类型改回Cell,不对其类型进行更改,单独对跟踪目标的储存,保证最小侵入
ChrisLv-CN Dec 12, 2025
671847d
调整houseClass的未知变量160b4为PowerSurplus
ChrisLv-CN Jan 11, 2026
5d6759c
添加新的调用
ChrisLv-CN Jan 11, 2026
4d329fb
从Phobos拿的改良版
ChrisLv-CN Jan 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion BasicStructures.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,26 @@ struct ColorStruct

inline explicit operator WORD() const;

operator bool()
{
return R != 0 || G != 0 || B != 0;
}

BYTE R, G, B;
};

// Helper
namespace Colors
{
static ColorStruct Empty{ 0, 0, 0 };
static ColorStruct Red{ 252, 0, 0 };
static ColorStruct Green{ 0, 252, 0 };
static ColorStruct Blue{ 0, 0, 252 };
static ColorStruct Yellow{ 252, 212, 0 };
static ColorStruct White{ 252, 252, 252 };
static ColorStruct Black{ 3, 3, 3 };
}

struct BytePalette {
ColorStruct Entries[256];

Expand Down Expand Up @@ -155,6 +172,11 @@ struct RandomStruct
struct RectangleStruct
{
int X, Y, Width, Height;

bool IsEmpty()
{
return X == 0 && Y == 0 && Width == 0 && Height == 0;
}
};

struct LTRBStruct
Expand All @@ -163,4 +185,4 @@ struct LTRBStruct
int Top;
int Right;
int Bottom;
};
};
5 changes: 5 additions & 0 deletions CCINIClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,11 @@ class CCINIClass : public INIClass
static constexpr reference<CCINIClass, 0x887208u> const INI_UIMD{};
static constexpr reference<CCINIClass, 0x8870C0u> const INI_RA2MD{};

// get the fileName
static constexpr reference<BYTE[], 0x826260u> const INI_Rules_FileName{};
static constexpr reference<BYTE[], 0x82621Cu> const INI_AI_FileName{};
static constexpr reference<BYTE[], 0x826254u> const INI_Art_FileName{};
Comment on lines +342 to +344
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The declarations for INI_Rules_FileName, INI_AI_FileName, and INI_Art_FileName as static constexpr reference<BYTE[]> constants are added. Verify that the memory addresses these constants point to are correctly assigned and that the data types are appropriate for their usage.


//non-static
CCINIClass() : INIClass(false)
{
Expand Down
59 changes: 59 additions & 0 deletions CellClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,31 @@ class TagClass;
class TiberiumClass;
class PixelFXClass;

enum class TileType : unsigned int
{
Unknown = 0,
Tunnel = 0x484AB0,
Water = 0x485060,
Blank = 0x486380,
Ramp = 0x4863A0,
Cliff = 0x4863D0,
Shore = 0x4865B0,
Wet = 0x4865D0,
MiscPave = 0x486650,
Pave = 0x486670,
DirtRoad = 0x486690,
PavedRoad = 0x4866D0,
PavedRoadEnd = 0x4866F0,
PavedRoadSlope = 0x486710,
Median = 0x486730,
Bridge = 0x486750,
WoodBridge = 0x486770,
ClearToSandLAT = 0x486790,
Green = 0x4867B0,
NotWater = 0x4867E0,
DestroyableCliff = 0x486900
};

class NOVTABLE CellClass : public AbstractClass
{
public:
Expand Down Expand Up @@ -192,6 +217,15 @@ class NOVTABLE CellClass : public AbstractClass
return buffer;
}

// pass
bool IsClearToMove(SpeedType speedType, bool ignoreInfantry, bool ignoreVehicles, ZoneType zone, MovementZone movementZone, int level, bool isBridge)
{ JMP_THIS(0x4834A0); }

bool IsClearToMove(SpeedType speedType, MovementZone movementZone, bool ignoreInfantry = false, bool ignoreVehicles = false, int level = -1)
{
return IsClearToMove(speedType, ignoreInfantry, ignoreInfantry, ZoneType::None, movementZone, level, ContainsBridge());
}
Comment on lines +223 to +230
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The overloaded IsClearToMove functions provide flexibility in determining whether a cell is clear for movement based on various parameters. This is a useful addition for handling different movement scenarios. However, there's a potential issue in the second overload (lines 224-227) where ignoreInfantry is passed twice instead of passing ignoreVehicles as the third argument to the first overload. This looks like a copy-paste error and should be corrected to ensure the function behaves as intended.

- return IsClearToMove(speedType, ignoreInfantry, ignoreInfantry, ZoneType::None, movementZone, level, (bool)(this->Flags & CellFlags::CenterRevealed));
+ return IsClearToMove(speedType, ignoreInfantry, ignoreVehicles, ZoneType::None, movementZone, level, (bool)(this->Flags & CellFlags::CenterRevealed));

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// pass
bool IsClearToMove(SpeedType speedType, bool ignoreInfantry, bool ignoreVehicles, ZoneType zone, MovementZone movementZone, int level, bool alt)
{ JMP_THIS(0x4834A0); }
bool IsClearToMove(SpeedType speedType, MovementZone movementZone, bool ignoreInfantry = false, bool ignoreVehicles = false, int level = -1)
{
return IsClearToMove(speedType, ignoreInfantry, ignoreInfantry, ZoneType::None, movementZone, level, (bool)(this->Flags & CellFlags::CenterRevealed));
}
// pass
bool IsClearToMove(SpeedType speedType, bool ignoreInfantry, bool ignoreVehicles, ZoneType zone, MovementZone movementZone, int level, bool alt)
{ JMP_THIS(0x4834A0); }
bool IsClearToMove(SpeedType speedType, MovementZone movementZone, bool ignoreInfantry = false, bool ignoreVehicles = false, int level = -1)
{
return IsClearToMove(speedType, ignoreInfantry, ignoreVehicles, ZoneType::None, movementZone, level, (bool)(this->Flags & CellFlags::CenterRevealed));
}


void ActivateVeins()
{ JMP_THIS(0x486920); }

Expand Down Expand Up @@ -291,6 +325,31 @@ class NOVTABLE CellClass : public AbstractClass
ISTILE(NotWater, 0x4867E0);
ISTILE(DestroyableCliff, 0x486900);

TileType GetTileType()
{
if (Tile_Is_Tunnel()) return TileType::Tunnel;
if (Tile_Is_Water()) return TileType::Water;
if (Tile_Is_Blank()) return TileType::Blank;
if (Tile_Is_Ramp()) return TileType::Ramp;
if (Tile_Is_Cliff()) return TileType::Cliff;
if (Tile_Is_Shore()) return TileType::Shore;
if (Tile_Is_Wet()) return TileType::Wet;
if (Tile_Is_MiscPave()) return TileType::MiscPave;
if (Tile_Is_Pave()) return TileType::Pave;
if (Tile_Is_DirtRoad()) return TileType::DirtRoad;
if (Tile_Is_PavedRoad()) return TileType::PavedRoad;
if (Tile_Is_PavedRoadEnd()) return TileType::PavedRoadEnd;
if (Tile_Is_PavedRoadSlope()) return TileType::PavedRoadSlope;
if (Tile_Is_Median()) return TileType::Median;
if (Tile_Is_Bridge()) return TileType::Bridge;
if (Tile_Is_WoodBridge()) return TileType::WoodBridge;
if (Tile_Is_ClearToSandLAT()) return TileType::ClearToSandLAT;
if (Tile_Is_Green()) return TileType::Green;
if (Tile_Is_NotWater()) return TileType::NotWater;
if (Tile_Is_DestroyableCliff()) return TileType::DestroyableCliff;
return TileType::Unknown;
}
Comment on lines +331 to +354
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GetTileType method uses a series of conditional checks to return the tile type. This approach is straightforward but consider if a more efficient mapping or querying mechanism is available, especially if this method is called frequently in performance-critical paths.


static CoordStruct Cell2Coord(const CellStruct &cell, int z = 0)
{
CoordStruct ret;
Expand Down
71 changes: 68 additions & 3 deletions Dir.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once
#pragma once

#include <bit>

Expand All @@ -11,8 +11,8 @@ enum class DirType : unsigned char;
struct DirStruct
{
public:
explicit DirStruct() noexcept : Raw { 0 } { }
explicit DirStruct(int raw) noexcept : Raw { static_cast<unsigned short>(raw) } { }
explicit DirStruct() noexcept : Raw{ 0 } { }
explicit DirStruct(int raw) noexcept : Raw{ static_cast<unsigned short>(raw) } { }
explicit DirStruct(double rad) noexcept { SetRadian<65536>(rad); }
explicit DirStruct(const DirType dir) noexcept { SetDir(dir); }
explicit DirStruct(const noinit_t&) noexcept { }
Expand Down Expand Up @@ -52,6 +52,25 @@ struct DirStruct
Raw = static_cast<unsigned short>(TranslateFixedPoint<Bits, 16>(value, offset));
}

// untemplate
short GetValue(const size_t Bits = 16)
{
if (Bits > 0 && Bits <= 16)
{
return (short)(TranslateFixedPoint(16, Bits, (size_t)(this->Raw), 0));
}
return 0;
}

// untemplate
void SetValue(short value, size_t Bits = 16, size_t offset = 0)
{
if (Bits > 0 && Bits <= 16)
{
Raw = static_cast<unsigned short>(TranslateFixedPoint(16, Bits, (size_t)value, offset));
}
}

template<size_t Count>
constexpr size_t GetFacing(size_t offset = 0) const
{
Expand Down Expand Up @@ -95,6 +114,31 @@ struct DirStruct
SetValue<Bits>(value & Max);
}

// untemplate
double GetRadian(size_t Bits = 16)
{
if (Bits > 0 && Bits <= 16)
{
int Max = (1 << (int)Bits) - 1;

int value = Max / 4 - this->GetValue(Bits);
return -value * -(Math::TwoPi / Max);
}
return 0;
}

// untemplate
void SetRadian(double rad, size_t Bits = 16)
{
if (Bits > 0 && Bits <= 16)
{
int Max = (1 << (int)Bits) - 1;

int value = (int)(rad * (Max / Math::TwoPi));
this->SetValue((short)(Max / 4 - value), Bits);
}
}

private:
template<size_t BitsFrom, size_t BitsTo>
constexpr static size_t TranslateFixedPoint(size_t value, size_t offset = 0)
Expand All @@ -110,6 +154,27 @@ struct DirStruct
return value & MaskOut;
}

// untemplate
constexpr static size_t TranslateFixedPoint(size_t bitsFrom, size_t bitsTo, size_t value, size_t offset = 0)
{
size_t MaskIn = (1u << (int)bitsFrom) - 1;
size_t MaskOut = (1u << (int)bitsTo) - 1;

if (bitsFrom > bitsTo)
{
// converting down
return (((((value & MaskIn) >> (int)(bitsFrom - bitsTo - 1)) + 1) >> 1) + offset) & MaskOut;
}
else if (bitsFrom < bitsTo)
{
// converting up
return (((value - offset) & MaskIn) << (int)(bitsTo - bitsFrom)) & MaskOut;
}
else
{
return value & MaskOut;
}
}
public:
unsigned short Raw;
private:
Expand Down
19 changes: 19 additions & 0 deletions DisplayClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@

class CCINIClass;
class ObjectTypeClass;
class BuildingTypeClass;

class NOVTABLE DisplayClass : public MapClass
{
public:
//Static
static constexpr constant_ptr<DisplayClass, 0x87F7E8u> const Instance{};

static constexpr reference<CellStruct, 0x88095Cu> const Display_ZoneCell{};
static constexpr reference<CellStruct, 0x880960u> const Display_ZoneOffset{};
static constexpr reference<CellStruct*, 0x880964u> const Display_CurrentFoundation_Data{};
static constexpr reference<bool, 0x880968u> const Display_PassedProximityCheck{};
static constexpr reference<BuildingTypeClass*, 0x880990u> const Display_PendingObject{};
static constexpr reference<int, 0x880994u> const Display_PendingHouse{};

//WIP: DisplayClass::TacticalClass goes HERE

bool ProcessClickCoords(Point2D *src, CellStruct *XYdst, CoordStruct *XYZdst, ObjectClass **Target, BYTE *a5, BYTE *a6)
Expand Down Expand Up @@ -65,6 +73,17 @@ class NOVTABLE DisplayClass : public MapClass
return outBuffer;
}

bool Passes_Proximity_Check(BuildingTypeClass* pPendingObject, int houseIndex, CellStruct* foundation, CellStruct* center)
{ JMP_THIS(0x4A8EB0); }

bool Passes_Proximity_Check()
{
CellStruct zoneCell = Display_ZoneCell.get();
CellStruct zoneOffset = Display_ZoneOffset.get();
CellStruct center = zoneCell + zoneOffset;
return Passes_Proximity_Check(Display_PendingObject.get(), Display_PendingHouse.get(), Display_CurrentFoundation_Data.get(), &center);
}

/* marks or unmarks the cells pointed to by CurrentFoundationData as containing a building */
void MarkFoundation(CellStruct * BaseCell, bool Mark)
{ JMP_THIS(0x4A95A0); }
Expand Down
2 changes: 2 additions & 0 deletions EBolt.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
#pragma once

#include <GeneralDefinitions.h>
#include <ArrayClasses.h>

class TechnoClass;
class UnitClass;

class EBolt
Expand Down
8 changes: 4 additions & 4 deletions Facing.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class FacingClass
DesiredFacing.SetDir(dir);
}

explicit FacingClass(const FacingClass& another) noexcept
FacingClass(const FacingClass& another) noexcept
: DesiredFacing { another.DesiredFacing }
, StartFacing { another.StartFacing }
, RotationTimer { another.RotationTimer }
Expand Down Expand Up @@ -132,8 +132,8 @@ class FacingClass

public:

DirStruct DesiredFacing;
DirStruct DesiredFacing; // target facing
DirStruct StartFacing; // The starting direction from which to calcuate the rotation.
CDTimerClass RotationTimer;
DirStruct ROT;
CDTimerClass RotationTimer; // counts rotation steps
DirStruct ROT; // Rate of Turn. INI Value * 256
};
3 changes: 3 additions & 0 deletions HouseClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <ScenarioClass.h>
#include <SessionClass.h>
#include <SideClass.h>
#include <SuperWeaponTypeClass.h>
#include <UnitClass.h>
#include <UnitTypeClass.h>

Expand Down Expand Up @@ -504,6 +505,8 @@ class NOVTABLE HouseClass : public AbstractClass, public IHouse, public IPublicH

SuperClass* FindSuperWeapon(SuperWeaponType type) const;

SuperClass* FindSuperWeapon(SuperWeaponTypeClass* type) const;

// I don't want to talk about these
// read the code <_<

Expand Down
2 changes: 1 addition & 1 deletion Kamikaze.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Kamikaze {
public:
struct KamikazeControl {
AircraftClass* Item;
CellClass* Cell;
AbstractClass* Cell; // Change to AbstractClass for Mission homing TechnoClass
};

static constexpr reference<Kamikaze, 0xABC5F8u> const Instance{};
Expand Down
4 changes: 3 additions & 1 deletion MessageListClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,12 @@ class MessageListClass
void PrintMessage(const wchar_t* pMessage, int durationFrames = 0x96, int nColorSchemeIndex = ColorScheme::White, bool bSilent = false)
{ this->AddMessage(nullptr, 0, pMessage, nColorSchemeIndex, static_cast<TextPrintType>(0x4046), durationFrames, bSilent); }

void PrintMessage(const wchar_t* pLabel, const wchar_t* pMessage, int durationFrames = 0x96, int nColorSchemeIndex = ColorScheme::White, bool bSilent = false)
{ this->AddMessage(pLabel, 0, pMessage, nColorSchemeIndex, static_cast<TextPrintType>(0x4046), static_cast<int>(durationFrames), bSilent); }

void PrintMessage(const wchar_t* pMessage, double durationMinutes, int nColorSchemeIndex = ColorScheme::White, bool bSilent = false)
{ this->AddMessage(nullptr, 0, pMessage, nColorSchemeIndex, static_cast<TextPrintType>(0x4046), static_cast<int>(durationMinutes * 900), bSilent); }


TextLabelClass* MessageList;
Point2D MessagePos;
int MaxMessageCount;
Expand Down
11 changes: 11 additions & 0 deletions ObjectClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <Audio.h>
#include <ObjectTypeClass.h>
#include <TagClass.h>
#include <RulesClass.h>

#include <Helpers/Template.h>

Expand Down Expand Up @@ -265,6 +266,16 @@ class NOVTABLE ObjectClass : public AbstractClass
return ret;
}

DamageState TakeDamage(int damage, WarheadTypeClass* pWH, bool crewed, bool ignoreDefenses = true, ObjectClass* pAttacker = nullptr, HouseClass* pAttackingHouse = nullptr)
{
return ReceiveDamage(&damage, 0, pWH, pAttacker, ignoreDefenses, !crewed, pAttackingHouse);
}
Comment on lines +271 to +274
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first TakeDamage method added to ObjectClass includes parameters for specifying a WarheadTypeClass. Ensure that the method correctly forwards these parameters to ReceiveDamage and that the logic for handling crewed and ignoreDefenses flags is correct.


DamageState TakeDamage(int damage, bool crewed, bool ignoreDefenses = true, ObjectClass* pAttacker = nullptr, HouseClass* pAttackingHouse = nullptr)
{
return TakeDamage(damage, RulesClass::Instance->C4Warhead, crewed, ignoreDefenses, pAttacker, pAttackingHouse);
}
Comment on lines +276 to +279
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second TakeDamage method simplifies damage application by using a default warhead type from RulesClass. Confirm that the default warhead type is appropriate for all use cases where this method might be called and that the forwarding of parameters to the first TakeDamage method is correct.


//Constructor NEVER CALL IT DIRECTLY
/*ObjectClass() noexcept
{ JMP_THIS(0x5F3900); }*/
Expand Down
4 changes: 2 additions & 2 deletions SpawnManagerClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class NOVTABLE SpawnManagerClass : public AbstractClass
DynamicVectorClass<SpawnNode*> SpawnedNodes;
CDTimerClass UpdateTimer;
CDTimerClass SpawnTimer;
AbstractClass* Target;
AbstractClass* NewTarget;
AbstractClass* Destination; // SpawnMissile's destination
AbstractClass* Target; // Spwan plane's target
SpawnManagerStatus Status;
};
Loading