aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-06-07 17:15:40 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-06-07 17:15:40 -0300
commit3d7fcfc4a6a1fc7016145b39596775bcd32be5c1 (patch)
treece0f9045c4b7647f8517ab9febb22edd414dc9bf /src
parentbd145c3ebfc082286486a8700b9ce20bfd7383e2 (diff)
downloadgame-3d7fcfc4a6a1fc7016145b39596775bcd32be5c1.tar.gz
game-3d7fcfc4a6a1fc7016145b39596775bcd32be5c1.zip
race loading
Diffstat (limited to 'src')
-rw-r--r--src/cr.hh17
-rw-r--r--src/crmain.cc456
-rw-r--r--src/crskill.cc70
-rw-r--r--src/enums.hh4
-rw-r--r--src/objects.cc3
-rw-r--r--src/stubs.hh7
6 files changed, 536 insertions, 21 deletions
diff --git a/src/cr.hh b/src/cr.hh
index a81b59b..ff96e88 100644
--- a/src/cr.hh
+++ b/src/cr.hh
@@ -16,6 +16,7 @@ struct TOutfit{
union{
uint16 ObjectType;
uint8 Colors[4];
+ uint32 PackedData;
};
};
@@ -742,6 +743,22 @@ void ExitKillStatistics(void);
bool IsRaceValid(int Race);
int GetRaceByName(const char *RaceName);
+const char *GetRaceName(int Race);
+TOutfit GetRaceOutfit(int Race);
+bool GetRaceNoSummon(int Race);
+bool GetRaceNoConvince(int Race);
+bool GetRaceNoIllusion(int Race);
+bool GetRaceNoParalyze(int Race);
+int GetRaceSummonCost(int Race);
+int GetRacePoison(int Race);
+bool GetRaceUnpushable(int Race);
+
+TOutfit ReadOutfit(TReadScriptFile *Script);
+void WriteOutfit(TReadScriptFile *Script, TOutfit Outfit);
+
+// crskill.cc
+// =============================================================================
+int GetSkillByName(const char *Name);
// crnonpl.cc
// =============================================================================
diff --git a/src/crmain.cc b/src/crmain.cc
index 6a9602d..48d31be 100644
--- a/src/crmain.cc
+++ b/src/crmain.cc
@@ -1239,7 +1239,461 @@ int GetRaceByName(const char *RaceName){
return Result;
}
-void LoadRaces(void); //TODO
+const char *GetRaceName(int Race){
+ if(!IsRaceValid(Race)){
+ error("GetRaceName: Ungültige Rassen-Nummer %d.\n", Race);
+ return NULL;
+ }
+
+ return RaceData[Race].Name;
+}
+
+TOutfit GetRaceOutfit(int Race){
+ if(!IsRaceValid(Race)){
+ error("GetRaceOutfit: Ungültige Rassen-Nummer %d.\n", Race);
+ return RaceData[1].Outfit;
+ }
+
+ return RaceData[Race].Outfit;
+}
+
+bool GetRaceNoSummon(int Race){
+ if(!IsRaceValid(Race)){
+ error("GetRaceNoSummon: Ungültige Rassen-Nummer %d.\n", Race);
+ return true;
+ }
+
+ return RaceData[Race].NoSummon;
+}
+
+bool GetRaceNoConvince(int Race){
+ if(!IsRaceValid(Race)){
+ error("GetRaceNoConvince: Ungültige Rassen-Nummer %d.\n", Race);
+ return true;
+ }
+
+ return RaceData[Race].NoConvince;
+}
+
+bool GetRaceNoIllusion(int Race){
+ if(!IsRaceValid(Race)){
+ error("GetRaceNoIllusion: Ungültige Rassen-Nummer %d.\n", Race);
+ return true;
+ }
+
+ return RaceData[Race].NoIllusion;
+}
+
+bool GetRaceNoParalyze(int Race){
+ if(!IsRaceValid(Race)){
+ error("GetRaceNoParalyze: Ungültige Rassen-Nummer %d.\n", Race);
+ return true;
+ }
+
+ return RaceData[Race].NoParalyze;
+}
+
+int GetRaceSummonCost(int Race){
+ if(!IsRaceValid(Race)){
+ error("GetRaceSummonCost: Ungültige Rassen-Nummer %d.\n", Race);
+ return 0;
+ }
+
+ return RaceData[Race].SummonCost;
+}
+
+int GetRacePoison(int Race){
+ if(!IsRaceValid(Race)){
+ error("GetRacePoison: Ungültige Rassen-Nummer %d.\n", Race);
+ return 0;
+ }
+
+ return RaceData[Race].Poison;
+}
+
+bool GetRaceUnpushable(int Race){
+ if(!IsRaceValid(Race)){
+ error("GetRaceUnpushable: Ungültige Rassen-Nummer %d.\n", Race);
+ return true;
+ }
+
+ return RaceData[Race].Unpushable;
+}
+
+// TODO(fusion): Probably move this somewhere else?
+TOutfit ReadOutfit(TReadScriptFile *Script){
+ TOutfit Outfit = {};
+ Script->readSymbol('(');
+ Outfit.OutfitID = Script->readNumber();
+ Script->readSymbol(',');
+ if(Outfit.OutfitID == 0){
+ Outfit.ObjectType = (uint16)Script->readNumber();
+ }else{
+ memcpy(Outfit.Colors, Script->readBytesequence(), sizeof(Outfit.Colors));
+ }
+ Script->readSymbol(')');
+}
+
+// TODO(fusion): Probably move this somewhere else?
+void WriteOutfit(TReadScriptFile *Script, TOutfit Outfit){
+ Script->writeText("(");
+ Script->writeNumber(Outfit.OutfitID);
+ Script->writeText(",");
+ if(Outfit.OutfitID == 0){
+ Script->writeNumber((int)Outfit.ObjectType);
+ }else{
+ Script->writeBytesequence(Outfit.Colors, sizeof(Outfit.Colors));
+ }
+ Script->writeText(")");
+}
+
+void LoadRace(const char *FileName){
+ TReadScriptFile Script;
+
+ Script.open(FileName);
+
+ // NOTE(fusion): It seems we expect `RaceNumber` to be the first attribute
+ // declared in a race file.
+ if(strcmp(Script.readIdentifier(), "racenumber") != 0){
+ Script.error("race number expected");
+ }
+
+ Script.readSymbol('=');
+
+ int RaceNumber = Script.readNumber();
+ if(!IsRaceValid(Race)){
+ Script.error("illegal race number");
+ }
+
+ TRaceData *Race = &RaceData[RaceNumber];
+ if(Race->Name[0] != 0){
+ Script.error("race already defined");
+ }
+
+ Race->Outfit = TOutfit{};
+ Race->Outfit.OutfitID = RaceNumber;
+
+ while(true){
+ Script.nextToken();
+ if(Script.Token == ENDOFFILE){
+ Script.close();
+ break;
+ }
+
+ char Identifier[MAX_IDENT_LENGTH];
+ strcpy(Identifier, Script.getIdentifier());
+ Script.readSymbol('=');
+
+ if(strcmp(Identifier, "name") == 0){
+ strcpy(Race->Name, Script.readString());
+ }else if(strcmp(Identifier, "article") == 0){
+ strcpy(Race->Article, Script.readString());
+ }else if(strcmp(Identifier, "outfit") == 0){
+ Race->Outfit = ReadOutfit(Script);
+ }else if(strcmp(Identifier, "corpse") == 0){
+ int CorpseTypeID = Script.readNumber();
+ Race->MaleCorpse = CorpseTypeID;
+ Race->FemaleCorpse = CorpseTypeID;
+ }else if(strcmp(Identifier, "corpses") == 0){
+ Race->MaleCorpse = Script.readNumber();
+ Script.readSymbol(',');
+ Race->FemaleCorpse = Script.readNumber();
+ }else if(strcmp(Identifier, "blood") == 0){
+ const char *Blood = Script.readIdentifier();
+ if(strcmp(Blood, "blood") == 0){
+ Race->Blood = BT_BLOOD;
+ }else if(strcmp(Blood, "slime") == 0){
+ Race->Blood = BT_SLIME;
+ }else if(strcmp(Blood, "bones") == 0){
+ Race->Blood = BT_BONES;
+ }else if(strcmp(Blood, "fire") == 0){
+ Race->Blood = BT_FIRE;
+ }else if(strcmp(Blood, "energy") == 0){
+ Race->Blood = BT_ENERGY;
+ }else{
+ Script.error("unknown blood type");
+ }
+ }else if(strcmp(Identifier, "experience") == 0){
+ Race->ExperiencePoints = Script.readNumber();
+ }else if(strcmp(Identifier, "summoncost") == 0){
+ Race->SummonCost = Script.readNumber();
+ }else if(strcmp(Identifier, "fleethreshold") == 0){
+ Race->FleeThreshold = Script.readNumber();
+ }else if(strcmp(Identifier, "attack") == 0){
+ Race->Attack = Script.readNumber();
+ }else if(strcmp(Identifier, "defend") == 0){
+ Race->Defend = Script.readNumber();
+ }else if(strcmp(Identifier, "armor") == 0){
+ Race->Armor = Script.readNumber();
+ }else if(strcmp(Identifier, "poison") == 0){
+ Race->Poison = Script.readNumber();
+ }else if(strcmp(Identifier, "losetarget") == 0){
+ Race->LoseTarget = Script.readNumber();
+ }else if(strcmp(Identifier, "strategy") == 0){
+ Script.readSymbol('(');
+ Race->Strategy[0] = Script.readNumber();
+ Script.readSymbol(',');
+ Race->Strategy[1] = Script.readNumber();
+ Script.readSymbol(',');
+ Race->Strategy[2] = Script.readNumber();
+ Script.readSymbol(',');
+ Race->Strategy[3] = Script.readNumber();
+ Script.readSymbol(')');
+ }else if(strcmp(Identifier, "flags") == 0){
+ Script.readSymbol('{');
+ do{
+ const char *Flag = Script.getIdentifier();
+ if(strcmp(Flag, "kickboxes") == 0){
+ Race->KickBoxes = true;
+ }else if(strcmp(Flag, "kickcreatures") == 0){
+ Race->KickCreatures = true;
+ }else if(strcmp(Flag, "seeinvisible") == 0){
+ Race->SeeInvisible = true;
+ }else if(strcmp(Flag, "unpushable") == 0){
+ Race->Unpushable = true;
+ }else if(strcmp(Flag, "distancefighting") == 0){
+ Race->DistanceFighting = true;
+ }else if(strcmp(Flag, "nosummon") == 0){
+ Race->NoSummon = true;
+ }else if(strcmp(Flag, "noconvince") == 0){
+ Race->NoConvince = true;
+ }else if(strcmp(Flag, "noillusion") == 0){
+ Race->NoIllusion = true;
+ }else if(strcmp(Flag, "noburning") == 0){
+ Race->NoBurning = true;
+ }else if(strcmp(Flag, "nopoison") == 0){
+ Race->NoPoison = true;
+ }else if(strcmp(Flag, "noenergy") == 0){
+ Race->NoEnergy = true;
+ }else if(strcmp(Flag, "nohit") == 0){
+ Race->NoHit = true;
+ }else if(strcmp(Flag, "nolifedrain") == 0){
+ Race->NoLifeDrain = true;
+ }else if(strcmp(Flag, "noparalyze") == 0){
+ Race->NoParalyze = true;
+ }else{
+ Script.error("unknown flag");
+ }
+ }while(Script.readSpecial() != '}');
+ }else if(strcmp(Identifier, "skills") == 0){
+ Script.readSymbol('{');
+ do{
+ Script.readSymbol('(');
+ int SkillNr = GetSkillByName(Script.readIdentifier());
+ if(SkillNr == -1){
+ Script.error("unknown skill name");
+ }
+
+ // NOTE(fusion): Skills are indexed from 1.
+ Race->Skills += 1;
+ TSkillData *SkillData = Race->Skill.at(Race->Skills);
+ SkillData->Nr = SkillNr;
+ Script.readSymbol(',');
+ SkillData->Actual = Script.readNumber();
+ Script.readSymbol(',');
+ SkillData->Minimum = Script.readNumber();
+ Script.readSymbol(',');
+ SkillData->Maximum = Script.readNumber();
+ Script.readSymbol(',');
+ SkillData->NextLevel = Script.readNumber();
+ Script.readSymbol(',');
+ SkillData->FactorPercent = Script.readNumber();
+ Script.readSymbol(',');
+ SkillData->AddLevel = Script.readNumber();
+ Script.readSymbol(')');
+ }while(Script.readSpecial() != '}');
+ }else if(strcmp(Identifier, "talk") == 0){
+ Script.readSymbol('{');
+ do{
+ // NOTE(fusion): Talks are indexed from 1.
+ Race->Talks += 1;
+ *Race->Talk.at(Race->Talks) = AddDynamicString(Script.readString());
+ }while(Script.readSpecial() != '}');
+ }else if(strcmp(Identifier, "inventory") == 0){
+ Script.readSymbol('{');
+ do{
+ Script.readSymbol('(');
+ // NOTE(fusion): Items are indexed from 1.
+ Race->Items += 1;
+ TItemData *ItemData = Race->Item.at(Race->Items);
+ ItemData->Type = Script.readNumber();
+ Script.readSymbol(',');
+ ItemData->Maximum = Script.readNumber();
+ Script.readSymbol(',');
+ ItemData->Probability = Script.readNumber();
+ Script.readSymbol(')');
+ }while(Script.readSpecial() != '}');
+ }else if(strcmp(Identifier, "spells") == 0){
+ Script.readSymbol('{');
+ do{
+ Race->Spells += 1;
+ TSpellData *SpellData = Race->Spell.at(Race->Spells);
+
+ // NOTE(fusion): Spell shape.
+ {
+ const char *SpellShape = Script.readIdentifier();
+ if(strcmp(SpellShape, "actor") == 0){
+ SpellData->Shape = SHAPE_ACTOR;
+ Script.readSymbol('(');
+ SpellData->ShapeParam1 = Script.readNumber();
+ Script.readSymbol(')');
+ }else if(strcmp(SpellShape, "victim") == 0){
+ SpellData->Shape = SHAPE_VICTIM;
+ Script.readSymbol('(');
+ SpellData->ShapeParam1 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ShapeParam2 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ShapeParam3 = Script.readNumber();
+ Script.readSymbol(')');
+ }else if(strcmp(SpellShape, "origin") == 0){
+ SpellData->Shape = SHAPE_ORIGIN;
+ Script.readSymbol('(');
+ SpellData->ShapeParam1 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ShapeParam2 = Script.readNumber();
+ Script.readSymbol(')');
+ }else if(strcmp(SpellShape, "destination") == 0){
+ SpellData->Shape = SHAPE_DESTINATION;
+ Script.readSymbol('(');
+ SpellData->ShapeParam1 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ShapeParam2 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ShapeParam3 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ShapeParam4 = Script.readNumber();
+ Script.readSymbol(')');
+ }else if(strcmp(SpellShape, "angle") == 0){
+ SpellData->Shape = SHAPE_ANGLE;
+ Script.readSymbol('(');
+ SpellData->ShapeParam1 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ShapeParam2 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ShapeParam3 = Script.readNumber();
+ Script.readSymbol(')');
+ }else{
+ Script.error("unknown spell shape");
+ }
+ }
+
+ Script.readSymbol('I');
+
+ // NOTE(fusion): Spell impact.
+ {
+ const char *SpellImpact = Script.readIdentifier();
+ if(strcmp(SpellImpact, "damage") == 0){
+ SpellData->Impact = IMPACT_DAMAGE;
+ Script.readSymbol('(');
+ SpellData->ImpactParam1 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ImpactParam2 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ImpactParam3 = Script.readNumber();
+ Script.readSymbol(')');
+ }else if(strcmp(SpellImpact, "field") == 0){
+ SpellData->Impact = IMPACT_FIELD;
+ Script.readSymbol('(');
+ SpellData->ImpactParam1 = Script.readNumber();
+ Script.readSymbol(')');
+ }else if(strcmp(SpellImpact, "healing") == 0){
+ SpellData->Impact = IMPACT_HEALING;
+ Script.readSymbol('(');
+ SpellData->ImpactParam1 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ImpactParam2 = Script.readNumber();
+ Script.readSymbol(')');
+ }else if(strcmp(SpellImpact, "speed") == 0){
+ SpellData->Impact = IMPACT_SPEED;
+ Script.readSymbol('(');
+ SpellData->ImpactParam1 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ImpactParam2 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ImpactParam3 = Script.readNumber();
+ Script.readSymbol(')');
+ }else if(strcmp(SpellImpact, "drunken") == 0){
+ SpellData->Impact = IMPACT_DRUNKEN;
+ Script.readSymbol('(');
+ SpellData->ImpactParam1 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ImpactParam2 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ImpactParam3 = Script.readNumber();
+ Script.readSymbol(')');
+ }else if(strcmp(SpellImpact, "strength") == 0){
+ SpellData->Impact = IMPACT_STRENGTH;
+ Script.readSymbol('(');
+ SpellData->ImpactParam1 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ImpactParam2 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ImpactParam3 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ImpactParam4 = Script.readNumber();
+ Script.readSymbol(')');
+ }else if(strcmp(SpellImpact, "outfit") == 0){
+ SpellData->Impact = IMPACT_OUTFIT;
+ Script.readSymbol('(');
+ TOutfit Outfit = ReadOutfit(Script);
+ SpellData->ImpactParam1 = Outfit.OutfitID;
+ SpellData->ImpactParam2 = (int)Outfit.PackedData;
+ Script.readSymbol(',');
+ SpellData->ImpactParam3 = Script.readNumber();
+ Script.readSymbol(')');
+ }else if(strcmp(SpellImpact, "summon") == 0){
+ SpellData->Impact = IMPACT_SUMMON;
+ Script.readSymbol('(');
+ SpellData->ImpactParam1 = Script.readNumber();
+ Script.readSymbol(',');
+ SpellData->ImpactParam2 = Script.readNumber();
+ Script.readSymbol(')');
+ }else{
+ Script.error("unknown spell impact");
+ }
+ }
+
+ Script.readSymbol(':');
+
+ // NOTE(fusion): Spell delay.
+ {
+ SpellData->Delay = Script.readNumber();
+ if(SpellData->Delay == 0){
+ Script.error("zero spell delay");
+ }
+ }
+ }while(Script.readSpecial() != '}');
+ }else{
+ Script.error("unknown race field");
+ }
+ }
+}
+
+void LoadRaces(void){
+ // TODO(fusion): It is possible to leak `MonsterDir` if `LoadRace` throws on
+ // errors (which it does). This is usually not a problem because failing here
+ // means we're cascading back to `InitAll` which will report the error and
+ // exit, but it is something to keep in mind for any functions that uses
+ // exceptions with non-RAII resources.
+
+ DIR *MonsterDir = opendir(MONSTERPATH);
+ if(MonsterDir == NULL){
+ error("LoadRaces: Unterverzeichnis %s nicht gefunden\n", MONSTERPATH);
+ throw "Cannot load races";
+ }
+
+ char FilePath[4096];
+ while(dirent *DirEntry = readdir(MonsterDir)){
+ const char *FileExt = findLast(DirEntry->d_name, '.');
+ if(FileExt != NULL && strcmp(FileExt, ".mon") == 0){
+ snprintf(FilePath, sizeof(FilePath), "%s/%s", MONSTERPATH, DirEntry->d_name);
+ LoadRace(FilePath);
+ }
+ }
+
+ closedir(MonsterDir);
+}
// Monster Raid
// =============================================================================
diff --git a/src/crskill.cc b/src/crskill.cc
index 8e259a8..84402ee 100644
--- a/src/crskill.cc
+++ b/src/crskill.cc
@@ -345,10 +345,10 @@ bool TSkillLevel::Jump(int Range){
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);
+ 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_STRENGTH]->Advance(Range);
AnnounceChangedCreature(this->Master->ID, 4);
this->Master->Combat.CheckCombatValues();
@@ -1142,7 +1142,7 @@ bool TSkillBase::NewSkill(uint16 SkillNo, TCreature *Creature){
case SKILL_HITPOINTS: Skill = new TSkillHitpoints(SkillNo, Creature); break;
case SKILL_MANA: Skill = new TSkillMana(SkillNo, Creature); break;
case SKILL_GO_STRENGTH: Skill = new TSkillGoStrength(SkillNo, Creature); break;
- case SKILL_CARRY_WEIGHT: Skill = new TSkillCarryStrength(SkillNo, Creature); break;
+ case SKILL_CARRY_STRENGTH: Skill = new TSkillCarryStrength(SkillNo, Creature); break;
case SKILL_FED: Skill = new TSkillFed(SkillNo, Creature); break;
case SKILL_LIGHT: Skill = new TSkillLight(SkillNo, Creature); break;
case SKILL_ILLUSION: Skill = new TSkillIllusion(SkillNo, Creature); break;
@@ -1164,10 +1164,8 @@ bool TSkillBase::SetSkills(int Race){
return false;
}
- // TODO(fusion): This is referencing some global table with probably all
- // types of creatures.
- int NumSkills = RaceData[Race].Skills;
- for(int i = 0; i < NumSkills; i += 1){
+ // NOTE(fusion): Skills are indexed from 1.
+ for(int i = 1; i <= RaceData[Race].Skills; i += 1){
TSkillData *SkillData = RaceData[Race].Skill.at(i);
// BUG(fusion): We don't check if `Skill` is valid? Could be NULL. We
@@ -1251,6 +1249,60 @@ void TSkillBase::DelTimer(uint16 SkNr){
}
}
+// Helpers
+//==============================================================================
+int GetSkillByName(const char *Name){
+ int Result = -1;
+ if(strcmp(Name, "level") == 0){
+ Result = SKILL_LEVEL;
+ }else if(strcmp(Name, "magiclevel") == 0){
+ Result = SKILL_MAGIC_LEVEL;
+ }else if(strcmp(Name, "hitpoints") == 0){
+ Result = SKILL_HITPOINTS;
+ }else if(strcmp(Name, "mana") == 0){
+ Result = SKILL_MANA;
+ }else if(strcmp(Name, "gostrength") == 0){
+ Result = SKILL_GO_STRENGTH;
+ }else if(strcmp(Name, "carrystrength") == 0){
+ Result = SKILL_CARRY_STRENGTH;
+ }else if(strcmp(Name, "shielding") == 0){
+ Result = SKILL_SHIELDING;
+ }else if(strcmp(Name, "distancefighting") == 0){
+ Result = SKILL_DISTANCE;
+ }else if(strcmp(Name, "swordfighting") == 0){
+ Result = SKILL_SWORD;
+ }else if(strcmp(Name, "clubfighting") == 0){
+ Result = SKILL_CLUB;
+ }else if(strcmp(Name, "axefighting") == 0){
+ Result = SKILL_AXE;
+ }else if(strcmp(Name, "fistfighting") == 0){
+ Result = SKILL_FIST;
+ }else if(strcmp(Name, "magicdefense") == 0){
+ Result = SKILL_MAGIC_DEFENSE;
+ }else if(strcmp(Name, "fishing") == 0){
+ Result = SKILL_FISHING;
+ }else if(strcmp(Name, "eating") == 0){
+ Result = SKILL_FED;
+ }else if(strcmp(Name, "shining") == 0){
+ Result = SKILL_LIGHT;
+ }else if(strcmp(Name, "illusion") == 0){
+ Result = SKILL_ILLUSION;
+ }else if(strcmp(Name, "poison") == 0){
+ Result = SKILL_POISON;
+ }else if(strcmp(Name, "burning") == 0){
+ Result = SKILL_BURNING;
+ }else if(strcmp(Name, "energy") == 0){
+ Result = SKILL_ENERGY;
+ }else if(strcmp(Name, "drunken") == 0){
+ Result = SKILL_DRUNK;
+ }else if(strcmp(Name, "manashield") == 0){
+ Result = SKILL_MANASHIELD;
+ }else if(strcmp(Name, "soulpoints") == 0){
+ Result = SKILL_SOUL;
+ }
+ return Result;
+}
+
// Initialization
//==============================================================================
void InitCrskill(void){
diff --git a/src/enums.hh b/src/enums.hh
index 8257677..4801e49 100644
--- a/src/enums.hh
+++ b/src/enums.hh
@@ -415,14 +415,14 @@ enum Skill: int {
SKILL_HITPOINTS = 2,
SKILL_MANA = 3,
SKILL_GO_STRENGTH = 4, // speed?
- SKILL_CARRY_WEIGHT = 5, // capacity?
+ SKILL_CARRY_STRENGTH = 5, // capacity?
SKILL_SHIELDING = 6,
SKILL_DISTANCE = 7,
SKILL_SWORD = 8,
SKILL_CLUB = 9,
SKILL_AXE = 10,
SKILL_FIST = 11,
- // 12?
+ SKILL_MAGIC_DEFENSE = 12,
SKILL_FISHING = 13,
SKILL_FED = 14,
SKILL_LIGHT = 15,
diff --git a/src/objects.cc b/src/objects.cc
index f617fb9..51171f0 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -576,8 +576,7 @@ static void LoadObjects(void){
}
}
}else{
- // TODO(fusion):
- // error("Invalid object type field \"%s\"", Identifier);
+ Script.error("Unknown object type field");
}
}
}
diff --git a/src/stubs.hh b/src/stubs.hh
index ba87f27..3495a59 100644
--- a/src/stubs.hh
+++ b/src/stubs.hh
@@ -40,13 +40,6 @@ extern TConnection *GetNextConnection(void);
extern const char *GetName(Object Obj);
extern Object GetObject(uint32 CreatureID, int x, int y, int z, int RNum, ObjectType Type);
extern TPlayer *GetPlayer(uint32 CreatureID);
-extern bool GetRaceNoConvince(int Race);
-extern bool GetRaceNoIllusion(int Race);
-extern bool GetRaceNoParalyze(int Race);
-extern bool GetRaceNoSummon(int Race);
-extern TOutfit GetRaceOutfit(int Race);
-extern int GetRacePoison(int Race);
-extern int GetRaceSummonCost(int Race);
extern void GraphicalEffect(int x, int y, int z, int Type);
extern void GraphicalEffect(Object Obj, int Type);
extern int IdentifyPlayer(const char *Name, bool ExactMatch, bool IgnoreGamemasters, TPlayer **Player);