diff options
| author | fusion32 <marcopuzziello@gmail.com> | 2025-05-16 18:46:18 -0300 |
|---|---|---|
| committer | fusion32 <marcopuzziello@gmail.com> | 2025-05-16 18:46:18 -0300 |
| commit | 717f5cd9dacf30fe6bf1561db9297e75fd27fdef (patch) | |
| tree | 4785a3bf770da880d514fc232a9972bd8473a72e /src | |
| download | game-717f5cd9dacf30fe6bf1561db9297e75fd27fdef.tar.gz game-717f5cd9dacf30fe6bf1561db9297e75fd27fdef.zip | |
initial commit - getting at TSkill structs
Diffstat (limited to 'src')
| -rw-r--r-- | src/creature.cc | 429 | ||||
| -rw-r--r-- | src/creature.hh | 76 | ||||
| -rw-r--r-- | src/enums.hh | 219 | ||||
| -rw-r--r-- | src/main.cc | 38 | ||||
| -rw-r--r-- | src/main.hh | 78 |
5 files changed, 840 insertions, 0 deletions
diff --git a/src/creature.cc b/src/creature.cc new file mode 100644 index 0000000..b6b046b --- /dev/null +++ b/src/creature.cc @@ -0,0 +1,429 @@ +#include "creature.hh" +#include "enums.hh" + +// TSkill REGULAR FUNCTIONS +//============================================================================== +TSkill::TSkill(int SkNr, TCreature *Master){ + this->Reset(); + this->SkNr = (uint16)SkNr; + this->Master = Master; +} + +int TSkill::Get(void){ + int Value = this->Act; + if(Value < this->Min) + Value = this->Min; + Value += this->MDAct + this->DAct; + return Value; +} + +int TSkill::GetProgress(void){ + int Result = 0; + if(this->NextLevel > this->LastLevel){ + Result = (this->NextLevel - this->Exp) * 100 / (this->NextLevel - this->LastLevel); + + // TODO(fusion): This feels too much for reporting a mostly *impossible* error. + if(Result < 0 || Result > 100){ + error("TSkill::GetProgress: Berechnungsfehler Exp %d, Last %d, Next %d, Prozent %d.\n", + this->Exp, this->LastLevel, this->NextLevel, Result); + + const char *MasterName = "(Unknown"; + if(this->Master != NULL){ + MasterName = this->Master->Name; + } + error("# Spieler %s - Skill %d\n", MasterName, this->SkNr); + Result = 0; + } + } + return Result; +} + +void TSkill::Check(void){ + if(this->Act > this->Max){ + this->Act = this->Max; + } +} + +void TSkill::Change(int Amount){ + this->Set(this->Act + Amount); + + // TODO(fusion): Probably `TSkill::Check` inlined? It doesn't make a whole + // lot of sense because `TSkill::Set` also checks the value. Maybe a custom + // version of it does something differently? + if(this->Act > this->Max){ + this->Act = this->Max; + } +} + +void TSkill::SetMDAct(int MDAct){ + this->MDAct = MDAct; + if(this->SkNr == 4 && this->Master && this->Master->Type == PLAYER){ + // TODO(fusion): Same as `TSkill::Process`. + ((TPlayer*)this->Master)->CheckState(); + } +} + +void TSkill::Load(int Act, int Max, int Min, int DAct, int MDAct, + int Cycle, int MaxCycle, int Count, int MaxCount, int AddLevel, + int Exp, int FactorPercent, int NextLevel, int Delta){ + this->Act = Act; + this->Max = Max; + this->Min = Min; + this->DAct = DAct; + this->MDAct = MDAct; + this->Cycle = Cycle; + this->MaxCycle = MaxCycle; + this->Count = Count; + this->MaxCount = MaxCount; + this->AddLevel = AddLevel; + this->Exp = Exp; + this->FactorPercent = FactorPercent; + this->NextLevel = NextLevel; + this->Delta = Delta; + + // TODO(fusion): Shouldn't we also do the same for `NextLevel`? + this->LastLevel = this->GetExpForLevel(Act); + + TCreature *Master = this->Master; + if(Master && Cycle != 0){ + int SkNr = this->SkNr; + if(SkNr >= NARRAY(Master->Skills)){ + error("TSkillBase::SetTimer: Ungueltige SkNr: %d\n", SkNr); + return; + } + + // TODO(fusion): I'm not entirely sure wtf is going on here. + TSkill *Other = Master->Skills[SkNr]; + Master->DelTimer(SkNr); + if(Other->SetTimer(Cycle, Count, MaxCount, FactorPercent)){ + Master->TimerList[Master->FirstFreeTimer] = Other; + Master->FirstFreeTimer += 1; + } + } +} + + +void TSkill::Save(int *Act, int *Max, int *Min, int *DAct, int *MDAct, + int *Cycle, int *MaxCycle, int *Count, int *MaxCount, int *AddLevel, + int *Exp, int *FactorPercent, int *NextLevel, int *Delta){ + *Act = this->Act; + *Max = this->Max; + *Min = this->Min; + *DAct = this->DAct; + *MDAct = this->MDAct; + *Cycle = this->Cycle; + *MaxCycle = this->MaxCycle; + *Count = this->Count; + *MaxCount = this->MaxCount; + *AddLevel = this->AddLevel; + *Exp = this->Exp; + *FactorPercent = this->FactorPercent; + *NextLevel = this->NextLevel; + *Delta = this->Delta; +} + +// TSkill VIRTUAL FUNCTIONS +//============================================================================== +TSkill::~TSkill(void){ + if(this->Master != NULL){ + this->Master->DelTimer(this->SkNr); + } +} + +void TSkill::Set(int Value){ + if(Value > this->Max) + Value = this->Max; + this->Act = Value; +} + +void TSkill::Increase(int Amount){ + // no-op +} + +void TSkill::Decrease(int Amount){ + // no-op +} + +int TSkill::GetExpForLevel(int Level){ + return 0; +} + +void TSkill::Advance(int Range){ + // no-op +} + +void TSkill::ChangeSkill(int FactorPercent, int Delta){ + // no-op +} + +int TSkill::ProbeValue(int Max, bool Increase){ + return 0; +} + +bool TSkill::Probe(int Diff, int Prob, bool Increase){ + return false; +} + +bool TSkill::Process(void){ + bool Result = this->Cycle == 0; + if(Result){ + if(this->Master && this->Master->Type == PLAYER){ + // TODO(fusion): Verify if a simple pointer cast works. Maybe `dynamic_cast`? + ((TPlayer*)this->Master)->CheckState(); + } + }else if(this->Count <= 0){ + this->Count = this->MaxCount; + // NOTE(fusion): `Range` should move `Cycle` towards ZERO. + int Range = (this->Cycle < 1) ? +1 : -1; + this->Cycle += Range; + this->Event(Range); + }else{ + this->Count -= 1; + } + + return Result; +} + +bool TSkill::SetTimer(int Cycle, int Count, int MaxCount, int AdditionalValue){ + this->Cycle = Cycle; + this->Count = Count; + this->MaxCount = MaxCount; + if(this->Master && this->Master->Type == PLAYER){ + // TODO(fusion): Same as `TSkill::Process`. + ((TPlayer*)this->Master)->CheckState(); + } + return true; +} + +bool TSkill::DelTimer(void){ + this->Cycle = 0; + this->Count = 0; + this->MaxCount = 0; + if(this->Master && this->Master->Type == PLAYER){ + // TODO(fusion): Same as `TSkill::Process`. + ((TPlayer*)this->Master)->CheckState(); + } + return true; +} + +int TSkill::TimerValue(void){ + return this->Cycle; +} + +bool TSkill::Jump(int Range){ + return true; +} + +void TSkill::Event(int Range){ + // no-op +} + +void TSkill::Reset(void){ + this->Act = 0; + this->Max = INT_MAX; + this->Min = 0; + this->DAct = 0; + this->MDAct = 0; + this->FactorPercent = 1000; + this->LastLevel = 0; + this->NextLevel = INT_MAX; + this->Exp = 0; + this->Delta = INT_MAX; + this->Cycle = 0; + this->MaxCycle = 0; + this->Count = 0; + this->MaxCount = 0; + this->AddLevel = 0; +} + +// TSkillLevel +//============================================================================== +TSkillLevel::~TSkillLevel(void){ + if(this->Master != NULL){ + this->Master->DelTimer(this->SkNr); + } +} + +void TSkillLevel::Increase(int Amount){ + if (Amount < 0) { + error("TSkillLevel::Increase: Amount negativ (%d).\n", Amount); + return; + } + + // BUG(fusion): No bounds check as in `TSkillLevel::Decrease`? + + int Range = 0; + this->Exp += Amount; + while(this->Exp >= this->NextLevel){ + this->Act += 1; + this->LastLevel = this->GetExpForLevel(this->Act); + this->NextLevel = this->GetExpForLevel(this->Act + 1); + if(this->NextLevel < 0){ + // BUG(fusion): We don't check if `Master` is valid here? + error("TSkillLevel::Increase: Skill vor Überlauf (%s, Skill %d).\n", this->Master->Name, this->SkNr); + this->NextLevel = this->Exp; + this->Exp -= 1000000; + break; + } + Range += 1; + } + + if(Range != 0){ + this->Jump(Range); + } + + if(this->Master == NULL){ + error("TSkillLevel::Increase: GetMaster liefert NULL zurueck.\n"); + return; + } + + if(this->Master->Type == PLAYER){ + SendPlayerData(this->Master->Connection); + } +} + +void TSkillLevel::Decrease(int Amount){ + if(Amount < 0){ + error("TSkillLevel::Decrease: Amount negativ (%d).\n", Amount); + return; + } + + // TODO(fusion): This is some weird ass comparison. + if(Amount > this->Exp && this->Exp > 100000){ + error("TSkillLevel::Decrease: Amount zu gross(%d).\n", Amount); + return; + } + + int Range = 0; + if(Amount < this->Exp){ + this->Exp -= Amount; + }else{ + this->Exp = 0; + } + + // TODO(fusion): This could probably be an oversight but the decompiled + // function was calling `GetExpForLevel` instead of using `LastLevel` + // which makes me wonder whether `LastLevel` is properly initialized. + while(this->Exp < this->LastLevel){ + this->Act -= 1; + this->NextLevel = this->LastLevel; + this->LastLevel = this->GetExpForLevel(this->Act); + } + + if(Range != 0){ + this->Jump(Range); + } + + if(this->Master == NULL){ + error("TSkillLevel::Decrease: GetMaster liefert NULL zurueck.\n"); + return; + } + + if(this->Master->Type == PLAYER){ + SendPlayerData(this->Master->Connection); + } +} + +int TSkillLevel::GetExpForLevel(int Level){ + if(Level < 1){ + error("TSkillLevel::GetExpForLevel: Ungültiger Level %d.\n", Level); + return 0; + } + + if(Level > 500){ + error("TSkillLevel::GetExpForLevel: Level=%d; Formel gegen Überlauf sichern.\n", Level); + return -1; + } + + if(this->Delta <= 0){ + error("TSkillLevel::GetExpForLevel: Ungültiger Delta-Wert %d.\n", this->Delta); + return 0; + } + + return ((((Level - 6) * Level + 17) * Level - 12) / 6) * this->Delta; +} + +bool TSkillLevel::Jump(int Range){ + if(this->Master == NULL){ + error("TSkillLevel::Jump: GetMaster liefert NULL zurueck!\n"); + return false; + } + + this->Master->Skills[SKILL_HITPOINTS ]->Advance(Range); + this->Master->Skills[SKILL_MANA ]->Advance(Range); + this->Master->Skills[SKILL_GO_STRENGTH ]->Advance(Range); + this->Master->Skills[SKILL_CARRY_WEIGHT]->Advance(Range); + + AnnounceChangedCreature(this->Master->ID, 4); + this->Master->Combat.CheckCombatValues(); + + if(this->Master->Type == PLAYER){ + // TODO(fusion): Probably `TSkill::Get` inlined? + int Level = this->Act; + if(Level < this->Min) + Level = this->Min; + Level += this->MDAct + this->DAct; + // == + + int FromLevel = Level - Range; + int ToLevel = Level; + if(Range > 0){ + SendMessage(this->Master->Connection, TALK_ANONYMOUS_BROADCAST, + "You advanced from Level %d to Level %d.", FromLevel, ToLevel); + }else if(Range < 0){ + SendMessage(this->Master->Connection, TALK_ANONYMOUS_BROADCAST, + "You were downgraded from Level %d to Level %d.", FromLevel, ToLevel); + } + } + + return true; +} + +// Creature Functions +//============================================================================== +// TODO(fusion): This was the first function I attempted to cleanup but soon +// realized we should start with the building blocks of the codebase, namely +// TSkill, TSkillBase, etc... +// We should probably come back to this once we start doing creature functions +// again. +void CheckMana(TCreature *Creature, int ManaPoints, int SoulPoints, int Delay){ + if(Creature == NULL){ + error("CheckMana: Übergebene Kreatur existiert nicht.\n"); + throw ERROR; + } + + if(Creature->Type != PLAYER || ManaPoints < 0) + return; + + TSkill *Mana = Creature->Skills[SKILL_MANA]; + if(Mana == NULL){ + error("CheckMana: Kein Skill MANA!\n"); + throw ERROR; + } + + TSkill *Soul = Creature->Skills[SKILL_SOUL]; + if(Soul == NULL){ + error("CheckMana: Kein Skill SOULPOINTS!\n"); + throw ERROR; + } + + if(!CheckRight(Creature->ID, UNLIMITED_MANA)){ + if(Mana->Get() < ManaPoints) + throw NOTENOUGHMANA; + + if(Soul->Get() < SoulPoints) + throw NOTENOUGHSOULPOINTS; + + Mana->Change(-ManaPoints); + Soul->Change(-SoulPoints); + } + + if(ManaPoints > 0){ + Creature->Skills[SKILL_MAGIC_LEVEL]->Increase(ManaPoints); + } + + // NOTE(fusion): Maintain largest exhaust? + int EarliestSpellTime = Delay + ServerMilliseconds; + if(Creature->EarliestSpellTime < EarliestSpellTime) + Creature->EarliestSpellTime = EarliestSpellTime; +} diff --git a/src/creature.hh b/src/creature.hh new file mode 100644 index 0000000..b471662 --- /dev/null +++ b/src/creature.hh @@ -0,0 +1,76 @@ +#ifndef TIBIA_CREATURE_HH_ +#define TIBIA_CREATURE_HH_ 1 + +#include "main.hh" + +struct TSkillBase; +struct TCreature; +struct TPlayer; + +struct TSkill{ + // REGULAR FUNCTIONS + // ========================================================================= + TSkill(int SkNr, TCreature *Master); + int Get(void); + int GetProgress(void); + void Check(void); + void Change(int Amount); + void SetMDAct(int MDAct); + void Load(int Act, int Max, int Min, int DAct, int MDAct, + int Cycle, int MaxCycle, int Count, int MaxCount, int AddLevel, + int Exp, int FactorPercent, int NextLevel, int Delta); + void Save(int *Act, int *Max, int *Min, int *DAct, int *MDAct, + int *Cycle, int *MaxCycle, int *Count, int *MaxCount, int *AddLevel, + int *Exp, int *FactorPercent, int *NextLevel, int *Delta); + + // VIRTUAL FUNCTIONS + // ========================================================================= + virtual ~TSkill(void); // VTABLE[ 0] + //virtual ~TSkill(void); // Duplicate destructor that also calls operator delete. // VTABLE[ 1] + virtual void Set(int Value); // VTABLE[ 2] + virtual void Increase(int Amount); // VTABLE[ 3] + virtual void Decrease(int Amount); // VTABLE[ 4] + virtual int GetExpForLevel(int Level); // VTABLE[ 5] + virtual void Advance(int Range); // VTABLE[ 6] + virtual void ChangeSkill(int FactorPercent, int Delta); // VTABLE[ 7] + virtual int ProbeValue(int Max, bool Increase); // VTABLE[ 8] + virtual bool Probe(int Diff, int Prob, bool Increase); // VTABLE[ 9] + virtual bool Process(void); // VTABLE[10] + virtual bool SetTimer(int Cycle, int Count, int MaxCount, int AdditionalValue); // VTABLE[11] + virtual bool DelTimer(void); // VTABLE[12] + virtual int TimerValue(void); // VTABLE[13] + virtual bool Jump(int Range); // VTABLE[14] + virtual void Event(int Range); // VTABLE[15] + virtual void Reset(void); // VTABLE[16] + + // DATA + // ========================================================================= + //void *VTABLE; // IMPLICIT + int DAct; // Delta Value - Probably from equipment. + int MDAct; // Delta Magic Value - Probably from spells. + uint16 SkNr; + TCreature *Master; + int Act; // Actual Value (?) + int Max; + int Min; + int FactorPercent; + int LastLevel; + int NextLevel; + int Delta; + int Exp; + int Cycle; + int MaxCycle; + int Count; + int MaxCount; + int AddLevel; +}; + +struct TSkillLevel: TSkill { + ~TSkillLevel(void) override; + void Increase(int Amount) override; + void Decrease(int Amount) override; + int GetExpForLevel(int Level) override; + bool Jump(int Range) override; +}; + +#endif //TIBIA_CREATURE_HH_ diff --git a/src/enums.hh b/src/enums.hh new file mode 100644 index 0000000..8212db1 --- /dev/null +++ b/src/enums.hh @@ -0,0 +1,219 @@ +#ifndef TIBIA_ENUMS_HH_ +#define TIBIA_ENUMS_HH_ 1 + +#include "main.hh" + +// TODO(fusion): Probably cleanup these names? Prefix values? Its crazy that +// there are no collision problems (possibly yet). + +enum CreatureType: int { + PLAYER = 0, + MONSTER = 1, + NPC = 2, +}; + +enum RESULT: int { + ERROR = -1, + NOERROR = 0, + NOTACCESSIBLE = 1, + NOTMOVABLE = 2, + NOTTAKABLE = 3, + NOROOM = 4, + OUTOFRANGE = 5, + OUTOFHOME = 6, + CANNOTTHROW = 7, + TOOHEAVY = 8, + CROSSREFERENCE = 9, + CONTAINERFULL = 10, + WRONGPOSITION = 11, + WRONGPOSITION2 = 12, + WRONGCLOTHES = 13, + HANDSNOTFREE = 14, + HANDBLOCKED = 15, + ONEWEAPONONLY = 16, + NOMATCH = 17, + NOTCUMULABLE = 18, + TOOMANYPARTS = 19, + EMPTYCONTAINER = 20, + SPLITOBJECT = 21, + NOKEYMATCH = 22, + UPSTAIRS = 23, + DOWNSTAIRS = 24, + CREATURENOTEXISTING = 25, + PLAYERNOTEXISTING = 26, + PLAYERNOTONLINE = 27, + NAMEAMBIGUOUS = 28, + NOTUSABLE = 29, + FEDUP = 30, + DESTROYED = 31, + SPELLUNKNOWN = 32, + LOWMAGICLEVEL = 33, + MAGICITEM = 34, + NOTENOUGHMANA = 35, + NOSKILL = 36, + TARGETLOST = 37, + OUTOFAMMO = 38, + NOCREATURE = 39, + TOOLONG = 40, + TARGETOUTOFRANGE = 41, + TARGETHIDDEN = 42, + ATTACKNOTALLOWED = 43, + NOWAY = 44, + LOGINERROR = 45, + LOGINABORT = 46, + PROTECTIONZONE = 47, + ENTERPROTECTIONZONE = 48, + EXHAUSTED = 49, + NOTINVITED = 50, + NOPREMIUMACCOUNT = 51, + MOVENOTPOSSIBLE = 52, + ALREADYTRADING = 53, + PARTNERTRADING = 54, + TOOMANYOBJECTS = 55, + TOOMANYSLAVES = 56, + NOTTURNABLE = 57, + SECUREMODE = 58, + NOTENOUGHSOULPOINTS = 59, + LOWLEVEL = 60, +}; + +enum RIGHT: int { + PREMIUM_ACCOUNT = 0, + NOTATION = 1, + NAMELOCK = 2, + STATEMENT_REPORT = 3, + BANISHMENT = 4, + FINAL_WARNING = 5, + IP_BANISHMENT = 6, + KICK = 7, + HOME_TELEPORT = 8, + GAMEMASTER_BROADCAST = 9, + ANONYMOUS_BROADCAST = 10, + NO_BANISHMENT = 11, + ALLOW_MULTICLIENT = 12, + LOG_COMMUNICATION = 13, + READ_GAMEMASTER_CHANNEL = 14, + READ_TUTOR_CHANNEL = 15, + HIGHLIGHT_HELP_CHANNEL = 16, + SEND_BUGREPORTS = 17, + NAME_INSULTING = 18, + NAME_SENTENCE = 19, + NAME_NONSENSICAL_LETTERS = 20, + NAME_BADLY_FORMATTED = 21, + NAME_NO_PERSON = 22, + NAME_CELEBRITY = 23, + NAME_COUNTRY = 24, + NAME_FAKE_IDENTITY = 25, + NAME_FAKE_POSITION = 26, + STATEMENT_INSULTING = 27, + STATEMENT_SPAMMING = 28, + STATEMENT_ADVERT_OFFTOPIC = 29, + STATEMENT_ADVERT_MONEY = 30, + STATEMENT_NON_ENGLISH = 31, + STATEMENT_CHANNEL_OFFTOPIC = 32, + STATEMENT_VIOLATION_INCITING = 33, + CHEATING_BUG_ABUSE = 34, + CHEATING_GAME_WEAKNESS = 35, + CHEATING_MACRO_USE = 36, + CHEATING_MODIFIED_CLIENT = 37, + CHEATING_HACKING = 38, + CHEATING_MULTI_CLIENT = 39, + CHEATING_ACCOUNT_TRADING = 40, + CHEATING_ACCOUNT_SHARING = 41, + GAMEMASTER_THREATENING = 42, + GAMEMASTER_PRETENDING = 43, + GAMEMASTER_INFLUENCE = 44, + GAMEMASTER_FALSE_REPORTS = 45, + KILLING_EXCESSIVE_UNJUSTIFIED = 46, + DESTRUCTIVE_BEHAVIOUR = 47, + SPOILING_AUCTION = 48, + INVALID_PAYMENT = 49, + TELEPORT_TO_CHARACTER = 50, + TELEPORT_TO_MARK = 51, + TELEPORT_VERTICAL = 52, + TELEPORT_TO_COORDINATE = 53, + LEVITATE = 54, + SPECIAL_MOVEUSE = 55, + MODIFY_GOSTRENGTH = 56, + SHOW_COORDINATE = 57, + RETRIEVE = 58, + ENTER_HOUSES = 59, + OPEN_NAMEDOORS = 60, + INVULNERABLE = 61, + UNLIMITED_MANA = 62, + KEEP_INVENTORY = 63, + ALL_SPELLS = 64, + UNLIMITED_CAPACITY = 65, + ZERO_CAPACITY = 66, + ATTACK_EVERYWHERE = 67, + NO_ATTACK = 68, + NO_RUNES = 69, + NO_LOGOUT_BLOCK = 70, + GAMEMASTER_OUTFIT = 71, + ILLUMINATE = 72, + CHANGE_PROFESSION = 73, + IGNORED_BY_MONSTERS = 74, + SHOW_KEYHOLE_NUMBERS = 75, + CREATE_OBJECTS = 76, + CREATE_MONEY = 77, + CREATE_MONSTERS = 78, + CHANGE_SKILLS = 79, + CLEANUP_FIELDS = 80, + NO_STATISTICS = 81, +}; + +// NOTE(fusion): This didn't exist int the decompiled version but is handy when +// accessing a creature's `Skills` table. +enum Skill: int { + SKILL_LEVEL = 0, + SKILL_MAGIC_LEVEL = 1, + SKILL_HITPOINTS = 2, + SKILL_MANA = 3, + SKILL_GO_STRENGTH = 4, // speed? + SKILL_CARRY_WEIGHT = 5, // capacity? + SKILL_FIST = 6, + SKILL_CLUB = 7, + SKILL_SWORD = 8, + SKILL_AXE = 9, + SKILL_DISTANCE = 10, + SKILL_SHIELDING = 11, + // 12? + SKILL_FISHING = 13, + SKILL_FED = 14, + SKILL_LIGHT = 15, + SKILL_ILLUSION = 16, + SKILL_POISON = 17, + SKILL_BURNING = 18, + SKILL_ENERGY = 19, + // 20? + // 21? + SKILL_SOUL = 22, +}; + +enum TalkMode: int { + TALK_SAY = 1, + TALK_WHISPER = 2, + TALK_YELL = 3, + TALK_PRIVATE_MESSAGE = 4, + TALK_CHANNEL_CALL = 5, + TALK_GAMEMASTER_REQUEST = 6, + TALK_GAMEMASTER_ANSWER = 7, + TALK_PLAYER_ANSWER = 8, + TALK_GAMEMASTER_BROADCAST = 9, + TALK_GAMEMASTER_CHANNELCALL = 10, + TALK_GAMEMASTER_MESSAGE = 11, + TALK_HIGHLIGHT_CHANNELCALL = 12, + TALK_ANONYMOUS_BROADCAST = 13, + TALK_ANONYMOUS_CHANNELCALL = 14, + TALK_ANONYMOUS_MESSAGE = 15, + TALK_ANIMAL_LOW = 16, + TALK_ANIMAL_LOUD = 17, + TALK_ADMIN_MESSAGE = 18, + TALK_EVENT_MESSAGE = 19, + TALK_LOGIN_MESSAGE = 20, + TALK_STATUS_MESSAGE = 21, + TALK_INFO_MESSAGE = 22, + TALK_FAILURE_MESSAGE = 23, +}; + +#endif //TIBIA_ENUMS_HH_ diff --git a/src/main.cc b/src/main.cc new file mode 100644 index 0000000..e616ce3 --- /dev/null +++ b/src/main.cc @@ -0,0 +1,38 @@ +#include "main.hh" + +#if 0 +// TODO(fusion): All globals should probably be packed into a `GlobalState` +// structure to minimize collisions and bugs. +struct GlobalState{ + // world state + // creatures + // items + // etc... +}; + +GlobalState G = {}; +#endif + +// TODO(fusion): Probably current server time. Used for delays, timers, etc. +int ServerMilliseconds = 0; + +void (*ErrorFunction)(const char*) = NULL; + +void error(char *Text, ...){ + char s[1024]; + + va_list ap; + va_start(ap, Text); + vsnprintf(s, sizeof(s) - 1, Text, ap); + va_end(ap); + + if(ErrorFunction){ + ErrorFunction(s); + }else{ + printf("%s", s); + } +} + +int main(int argc, char **argv){ + return 0; +} diff --git a/src/main.hh b/src/main.hh new file mode 100644 index 0000000..ad4f3ca --- /dev/null +++ b/src/main.hh @@ -0,0 +1,78 @@ +#ifndef TIBIA_MAIN_HH_ +#define TIBIA_MAIN_HH_ 1 + +#include <float.h> +#include <limits.h> +#include <stddef.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uintptr_t uintptr; +typedef size_t usize; + +#define STATIC_ASSERT(expr) static_assert((expr), "static assertion failed: " #expr) +#define NARRAY(arr) (sizeof(arr) / sizeof(arr[0])) +#define ISPOW2(x) ((x) != 0 && ((x) & ((x) - 1)) == 0) +#define KB(x) ((usize)(x) << 10) +#define MB(x) ((usize)(x) << 20) +#define GB(x) ((usize)(x) << 30) + +// TODO(fusion): We might not actually compile the output for the decompilation +// step but if we did, we'd need to make sure we're compiling in 32 bits mode. +STATIC_ASSERT(sizeof(bool) == 1); +STATIC_ASSERT(sizeof(int) == 4); +//STATIC_ASSERT(sizeof(void*) == 4); + +#if !OS_WINDOWS && !OS_LINUX +# if defined(_WIN32) +# define OS_WINDOWS 1 +# elif defined(__linux__) || defined(__gnu_linux__) +# define OS_LINUX 1 +# else +# error "Operating system not supported." +# endif +#endif + +#if !COMPILER_MSVC && !COMPILER_GCC && !COMPILER_CLANG +# if defined(_MSC_VER) +# define COMPILER_MSVC 1 +# elif defined(__GNUC__) +# define COMPILER_GCC 1 +# elif defined(__clang__) +# define COMPILER_CLANG 1 +# endif +#endif + +// NOTE(fusion): Compiler attributes. +#if COMPILER_GCC || COMPILER_CLANG +# define ATTR_FALLTHROUGH __attribute__((fallthrough)) +# define ATTR_PRINTF(x, y) __attribute__((format(printf, x, y))) +#else +# define ATTR_FALLTHROUGH +# define ATTR_PRINTF(x, y) +#endif + +#if COMPILER_MSVC +# define TRAP() __debugbreak(); +#elif COMPILER_GCC || COMPILER_CLANG +# define TRAP() __builtin_trap() +#else +# define TRAP() abort() +#endif + +#define ASSERT_ALWAYS(expr) if(!(expr)) { TRAP(); } +#if BUILD_DEBUG +# define ASSERT(expr) ASSERT_ALWAYS(expr) +#else +# define ASSERT(expr) ((void)(expr)) +#endif + +void error(char *Text, ...) ATTR_PRINTF(1, 2); + +#endif //TIBIA_MAIN_HH_ |
