diff --git doc/data_format.rst doc/data_format.rst index 1595824..57d1faf 100644 --- doc/data_format.rst +++ doc/data_format.rst @@ -1442,7 +1442,7 @@ Persons ======= Persons are an important concept in the game. Their properties are defined in the game blocks below. -FreeRCT can read blocks with version 1. +FreeRCT can read blocks with version 1 or 2. ====== ====== ========================================================== Offset Length Description @@ -1471,9 +1471,18 @@ Offset Length Description A person type defines the kind of persons: -- *Any* (0) Any kind of person (eg persons are not shown). -- *Pillar* (8) Guests from the Pillar Planet (test graphics). -- *Earth* (16) Earth-bound persons. +============ ===== ======= ============================================ +Name Value Version Description +============ ===== ======= ============================================ +Any 0 1- Any kind of person (persons are not shown). +Pillar 8 1 Guests from the Pillar planet (testing). +Guest 8 2- Guests. +Earth 16 1 Earth-bound persons. +Handyman 17 2- Handymen. +Mechanic 18 2- Mechanics. +Guard 19 2- Security guards. +Entertainer 20 2- Entertainers. +============ ===== ======= ============================================ The *any* kind is used as fall back. @@ -1490,6 +1499,8 @@ Version history ............... - 1 (20120708) Initial version. +- 2 (20141230) Renamed type 'Pillar' to 'Guest', removed type 'Earth', and + added staff types (Handyman, Mechanic, Guard, Entertainer). Animation diff --git graphics/rcd/freerct.txt graphics/rcd/freerct.txt index 10ff505..36f424d 100644 --- graphics/rcd/freerct.txt +++ graphics/rcd/freerct.txt @@ -651,7 +651,7 @@ file("freerct.rcd") { // Person type graphics. PRSG { person_graphics { - person_type: pillar; + person_type: guest; recolour { original: grey; replace: bitset(yellow, green, blue, orange, pink); @@ -661,14 +661,14 @@ file("freerct.rcd") { // NE walking. ANIM { - person_type: pillar; + person_type: guest; anim_type: walk_ne; frame_data { duration: 40; change_x: -4; change_y: 0; } } ANSP { tile_width: 64; - person_type: pillar; + person_type: guest; anim_type: walk_ne; sprite { @@ -679,14 +679,14 @@ file("freerct.rcd") { // SE walking. ANIM { - person_type: pillar; + person_type: guest; anim_type: walk_se; frame_data { duration: 40; change_x: 0; change_y: 4; } } ANSP { tile_width: 64; - person_type: pillar; + person_type: guest; anim_type: walk_se; sprite { @@ -697,14 +697,14 @@ file("freerct.rcd") { // SW walking. ANIM { - person_type: pillar; + person_type: guest; anim_type: walk_sw; frame_data { duration: 40; change_x: 4; change_y: 0; } } ANSP { tile_width: 64; - person_type: pillar; + person_type: guest; anim_type: walk_sw; sprite { @@ -715,14 +715,346 @@ file("freerct.rcd") { // NW walking. ANIM { - person_type: pillar; + person_type: guest; anim_type: walk_nw; frame_data { duration: 40; change_x: 0; change_y: -4; } } ANSP { tile_width: 64; - person_type: pillar; + person_type: guest; + anim_type: walk_nw; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // Handyman - person type graphics. + PRSG { + person_graphics { + person_type: handyman; + recolour { + original: grey; + replace: bitset(grey); + } + } + } + + // NE walking. + ANIM { + person_type: handyman; + anim_type: walk_ne; + + frame_data { duration: 40; change_x: -4; change_y: 0; } + } + ANSP { + tile_width: 64; + person_type: handyman; + anim_type: walk_ne; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // SE walking. + ANIM { + person_type: handyman; + anim_type: walk_se; + + frame_data { duration: 40; change_x: 0; change_y: 4; } + } + ANSP { + tile_width: 64; + person_type: handyman; + anim_type: walk_se; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // SW walking. + ANIM { + person_type: handyman; + anim_type: walk_sw; + + frame_data { duration: 40; change_x: 4; change_y: 0; } + } + ANSP { + tile_width: 64; + person_type: handyman; + anim_type: walk_sw; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // NW walking. + ANIM { + person_type: handyman; + anim_type: walk_nw; + + frame_data { duration: 40; change_x: 0; change_y: -4; } + } + ANSP { + tile_width: 64; + person_type: handyman; + anim_type: walk_nw; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // Mechanic - person type graphics. + PRSG { + person_graphics { + person_type: mechanic; + recolour { + original: grey; + replace: bitset(grey); + } + } + } + + // NE walking. + ANIM { + person_type: mechanic; + anim_type: walk_ne; + + frame_data { duration: 40; change_x: -4; change_y: 0; } + } + ANSP { + tile_width: 64; + person_type: mechanic; + anim_type: walk_ne; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // SE walking. + ANIM { + person_type: mechanic; + anim_type: walk_se; + + frame_data { duration: 40; change_x: 0; change_y: 4; } + } + ANSP { + tile_width: 64; + person_type: mechanic; + anim_type: walk_se; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // SW walking. + ANIM { + person_type: mechanic; + anim_type: walk_sw; + + frame_data { duration: 40; change_x: 4; change_y: 0; } + } + ANSP { + tile_width: 64; + person_type: mechanic; + anim_type: walk_sw; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // NW walking. + ANIM { + person_type: mechanic; + anim_type: walk_nw; + + frame_data { duration: 40; change_x: 0; change_y: -4; } + } + ANSP { + tile_width: 64; + person_type: mechanic; + anim_type: walk_nw; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // Security guard - person type graphics. + PRSG { + person_graphics { + person_type: guard; + recolour { + original: grey; + replace: bitset(grey); + } + } + } + + // NE walking. + ANIM { + person_type: guard; + anim_type: walk_ne; + + frame_data { duration: 40; change_x: -4; change_y: 0; } + } + ANSP { + tile_width: 64; + person_type: guard; + anim_type: walk_ne; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // SE walking. + ANIM { + person_type: guard; + anim_type: walk_se; + + frame_data { duration: 40; change_x: 0; change_y: 4; } + } + ANSP { + tile_width: 64; + person_type: guard; + anim_type: walk_se; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // SW walking. + ANIM { + person_type: guard; + anim_type: walk_sw; + + frame_data { duration: 40; change_x: 4; change_y: 0; } + } + ANSP { + tile_width: 64; + person_type: guard; + anim_type: walk_sw; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // NW walking. + ANIM { + person_type: guard; + anim_type: walk_nw; + + frame_data { duration: 40; change_x: 0; change_y: -4; } + } + ANSP { + tile_width: 64; + person_type: guard; + anim_type: walk_nw; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // Entertainer - person type graphics. + PRSG { + person_graphics { + person_type: entertainer; + recolour { + original: grey; + replace: bitset(grey); + } + } + } + + // NE walking. + ANIM { + person_type: entertainer; + anim_type: walk_ne; + + frame_data { duration: 40; change_x: -4; change_y: 0; } + } + ANSP { + tile_width: 64; + person_type: entertainer; + anim_type: walk_ne; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // SE walking. + ANIM { + person_type: entertainer; + anim_type: walk_se; + + frame_data { duration: 40; change_x: 0; change_y: 4; } + } + ANSP { + tile_width: 64; + person_type: entertainer; + anim_type: walk_se; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // SW walking. + ANIM { + person_type: entertainer; + anim_type: walk_sw; + + frame_data { duration: 40; change_x: 4; change_y: 0; } + } + ANSP { + tile_width: 64; + person_type: entertainer; + anim_type: walk_sw; + + sprite { + x_base: 0; y_base: 0; width: 10; height: 27; + x_offset: -5; y_offset: -27; file: "../sprites/gui/pillar.png"; + } + } + + // NW walking. + ANIM { + person_type: entertainer; + anim_type: walk_nw; + + frame_data { duration: 40; change_x: 0; change_y: -4; } + } + ANSP { + tile_width: 64; + person_type: entertainer; anim_type: walk_nw; sprite { diff --git src/people.cpp src/people.cpp index 7696121..f798c08 100644 --- src/people.cpp +++ src/people.cpp @@ -86,16 +86,16 @@ Guests::~Guests() void Guests::Initialize() { this->valid_ptypes = 0; - for (PersonType pertype = PERSON_MIN_GUEST; pertype <= PERSON_MAX_GUEST; pertype++) { - bool usable = true; - for (AnimationType antype = ANIM_BEGIN; antype <= ANIM_LAST; antype++) { - if (_sprite_manager.GetAnimation(antype, pertype) == nullptr) { - usable = false; - break; - } + PersonType pertype = PERSON_GUEST; + bool usable = true; + + for (AnimationType antype = ANIM_BEGIN; antype <= ANIM_LAST; antype++) { + if (_sprite_manager.GetAnimation(antype, pertype) == nullptr) { + usable = false; + break; } - if (usable) this->valid_ptypes |= 1u << (pertype - PERSON_MIN_GUEST); } + if (usable) this->valid_ptypes |= 1u << (pertype - PERSON_ANY); } /** @@ -105,8 +105,8 @@ void Guests::Initialize() */ bool Guests::CanUsePersonType(PersonType ptype) { - if (ptype < PERSON_MIN_GUEST || ptype > PERSON_MAX_GUEST) return false; - return (this->valid_ptypes & (1 << (ptype - PERSON_MIN_GUEST))) != 0; + if (ptype != PERSON_GUEST) return false; + return (this->valid_ptypes & (1 << (ptype - PERSON_ANY))) != 0; } /** @@ -196,7 +196,7 @@ void Guests::DoTick() */ void Guests::OnNewDay() { - PersonType ptype = PERSON_PILLAR; + PersonType ptype = PERSON_GUEST; if (!this->CanUsePersonType(ptype)) return; if (this->CountActiveGuests() >= _scenario.max_guests) return; if (!this->rnd.Success1024(_scenario.GetSpawnProbability(512))) return; diff --git src/people.h src/people.h index de3fa27..0895d12 100644 --- src/people.h +++ src/people.h @@ -60,6 +60,7 @@ protected: /** * All our guests. * @todo Allow to have several blocks of guests. + * @todo valid_ptypes should be removed. */ class Guests { public: @@ -113,7 +114,7 @@ private: void AddFree(Guest *g); Guest *GetFree(); }; -assert_compile(PERSON_MAX_GUEST - PERSON_MIN_GUEST + 1 <= 16); ///< Verify that all person types fit in #Guests::valid_ptypes +assert_compile(PERSON_GUEST + 1 <= 16); ///< Verify that all person types fit in #Guests::valid_ptypes extern Guests _guests; diff --git src/person.cpp src/person.cpp index d19d514..5d92f68 100644 --- src/person.cpp +++ src/person.cpp @@ -58,7 +58,7 @@ PersonTypeData &ModifyPersonTypeData(PersonType pt) bool LoadPRSG(RcdFileReader *rcd_file) { uint32 length = rcd_file->size; - if (rcd_file->version != 1 || length < 1) return false; + if (rcd_file->version < 1 || rcd_file->version > 2 || length < 1) return false; uint8 count = rcd_file->GetUInt8(); length--; @@ -71,8 +71,12 @@ bool LoadPRSG(RcdFileReader *rcd_file) PersonType pt; switch (ps) { - case 8: pt = PERSON_PILLAR; break; - case 16: pt = PERSON_EARTH; break; + case 8: + case 16: pt = PERSON_GUEST; break; + case 17: pt = PERSON_HANDYMAN; break; + case 18: pt = PERSON_MECHANIC; break; + case 19: pt = PERSON_GUARD; break; + case 20: pt = PERSON_ENTERTAINER; break; default: pt = PERSON_INVALID; break; } diff --git src/person.h src/person.h index 4485913..b7a9058 100644 --- src/person.h +++ src/person.h @@ -121,7 +121,7 @@ public: */ bool IsGuest() const { - return this->type >= PERSON_MIN_GUEST && this->type <= PERSON_MAX_GUEST; + return this->type == PERSON_GUEST; } void SetName(const char *name); diff --git src/person_type.h src/person_type.h index 20d25d2..47be967 100644 --- src/person_type.h +++ src/person_type.h @@ -19,15 +19,15 @@ class RcdFileReader; /** Types of persons. */ enum PersonType { - PERSON_ANY = 0, ///< No people displayed in the animation. - PERSON_PILLAR = 1, ///< %Guests from the planet of Pillars (test graphics). - PERSON_EARTH = 2, ///< Earth-bound guests. - PERSON_TYPE_COUNT, ///< Number of known types of persons. + PERSON_ANY, ///< No people displayed in the animation. + PERSON_GUEST, ///< %Guests. + PERSON_HANDYMAN, ///< %Staff handymen. + PERSON_MECHANIC, ///< %Staff mechanics. + PERSON_GUARD, ///< %Staff security guards. + PERSON_ENTERTAINER, ///< %Staff entertainers. + PERSON_TYPE_COUNT, ///< Number of known types of persons. PERSON_INVALID = 0xFF, ///< Invalid person type. - - PERSON_MIN_GUEST = PERSON_ANY, ///< First value of a guest. - PERSON_MAX_GUEST = PERSON_EARTH, ///< Last value of a guest. }; DECLARE_POSTFIX_INCREMENT(PersonType) diff --git src/rcdgen/check_data.cpp src/rcdgen/check_data.cpp index 260441c..72f59b8 100644 --- src/rcdgen/check_data.cpp +++ src/rcdgen/check_data.cpp @@ -1071,12 +1071,15 @@ static std::shared_ptr ConvertPRSGNode(std::shared_ptr ng) /** Symbols for an ANIM and ANSP blocks. */ static const Symbol _anim_symbols[] = { - {"pillar", 8}, - {"earth", 16}, - {"walk_ne", 1}, // Walk in north-east direction. - {"walk_se", 2}, // Walk in south-east direction. - {"walk_sw", 3}, // Walk in south-west direction. - {"walk_nw", 4}, // Walk in north-west direction. + {"guest", 8}, + {"handyman", 17}, + {"mechanic", 18}, + {"guard", 19}, + {"entertainer", 20}, + {"walk_ne", 1}, // Walk in north-east direction. + {"walk_se", 2}, // Walk in south-east direction. + {"walk_sw", 3}, // Walk in south-west direction. + {"walk_nw", 4}, // Walk in north-west direction. {nullptr, 0} }; @@ -1501,8 +1504,11 @@ static std::shared_ptr ConvertBitMaskNode(std::shared_ptr ng /** Names of person types and colour ranges. */ static const Symbol _person_graphics_symbols[] = { - {"pillar", 8}, - {"earth", 16}, + {"guest", 8}, + {"handyman", 17}, + {"mechanic", 18}, + {"guard", 19}, + {"entertainer", 20}, {"grey", COL_GREY}, {"green_brown", COL_GREEN_BROWN}, {"orange_brown", COL_ORANGE_BROWN}, diff --git src/rcdgen/nodes.cpp src/rcdgen/nodes.cpp index 4295917..fb00cb6 100644 --- src/rcdgen/nodes.cpp +++ src/rcdgen/nodes.cpp @@ -493,7 +493,7 @@ bool PersonGraphics::AddRecolour(uint8 orig, uint32 replace) return false; } -PRSGBlock::PRSGBlock() : GameBlock("PRSG", 1) +PRSGBlock::PRSGBlock() : GameBlock("PRSG", 2) { } diff --git src/sprite_store.cpp src/sprite_store.cpp index cea7fd4..92ebc45 100644 --- src/sprite_store.cpp +++ src/sprite_store.cpp @@ -605,8 +605,12 @@ static PersonType DecodePersonType(uint8 pt) { switch (pt) { case 0: return PERSON_ANY; - case 8: return PERSON_PILLAR; - case 16: return PERSON_EARTH; + case 8: + case 16: return PERSON_GUEST; + case 17: return PERSON_HANDYMAN; + case 18: return PERSON_MECHANIC; + case 19: return PERSON_GUARD; + case 20: return PERSON_ENTERTAINER; default: return PERSON_INVALID; } }