1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-26 14:37:44 +00:00

Merge pull request #428 from NotAdam/housing

Add ward selection, ward info & some script cleanup
This commit is contained in:
Mordred 2018-11-20 13:21:54 +01:00 committed by GitHub
commit cfca3f4e2f
16 changed files with 256 additions and 115 deletions

View file

@ -814,6 +814,30 @@ namespace Core::Common
heart = 0x06 heart = 0x06
}; };
enum HousingAppeal : uint8_t
{
NoAppeal = 0,
Emporium = 1,
Botique = 2,
DesignerHome = 3,
MessageBook = 4,
Tavern = 5,
Eatery = 6,
ImmersiveExperience = 7,
Aquarium = 9,
Sanctum = 10,
Venue = 11,
};
enum WardEstateFlags : uint8_t
{
IsEstateOwned = 1,
IsPublicEstate = 2,
HasEstateMessage = 4,
EstateFlagUnknown = 8,
IsFreeCompanyEstate = 16,
};
using PlayerStateFlagList = std::vector< PlayerStateFlag >; using PlayerStateFlagList = std::vector< PlayerStateFlag >;
} }

View file

@ -292,8 +292,10 @@ enum ActorControlType : uint16_t
RequestHousingBuildPreset = 0x44C, RequestHousingBuildPreset = 0x44C,
RequestLandSignFree = 0x451, RequestLandSignFree = 0x451,
RequestLandSignOwned = 0x452, RequestLandSignOwned = 0x452,
RequestWardLandInfo = 0x453,
RequestLandRelinquish = 0x454, RequestLandRelinquish = 0x454,
RequestEstateRename = 0x45A, RequestEstateRename = 0x45A,
RequestEstateGreeting = 0x45C,
RequestHousingItemUI = 0x463, RequestHousingItemUI = 0x463,
RequestSharedEstateSettings = 0x46F, RequestSharedEstateSettings = 0x46F,

View file

@ -82,7 +82,7 @@ namespace Core::Network::Packets
ServerNotice = 0x0104, // updated 4.4 ServerNotice = 0x0104, // updated 4.4
SetOnlineStatus = 0x0105, // updated 4.4 SetOnlineStatus = 0x0105, // updated 4.4
CountdownInitiate = 0x010C, // updated 4.4 CountdownInitiate = 0x010C, // updated 4.4
CountdownCancel = 0x010D, // updated 4.4 CountdownCancel = 0x010D, // updated 4.4
@ -192,11 +192,12 @@ namespace Core::Network::Packets
LandRename = 0x0226, // updated 4.4 LandRename = 0x0226, // updated 4.4
LandPermissionSlot = 0x0228, // updated 4.4 LandPermissionSlot = 0x0228, // updated 4.4
LandPermission = 0x0229, // updated 4.4 LandPermission = 0x0229, // updated 4.4
LandSetYardInitialize = 0x022C, // updated 4.4 LandSetYardInitialize = 0x022C, // updated 4.4
HousingWardInfo = 0x022F, // updated 4.4
YardObjectMove = 0x0230, // updated 4.4 YardObjectMove = 0x0230, // updated 4.4
SharedEstateSettingsResponse = 0x023C, // updated 4.4 SharedEstateSettingsResponse = 0x023C, // updated 4.4

View file

@ -1720,6 +1720,24 @@ struct FFXIVIpcLandSetYardInitialize : FFXIVIpcBasePacket< LandSetYardInitialize
uint32_t unknown4; //unused uint32_t unknown4; //unused
}; };
struct FFXIVIpcHousingWardInfo : FFXIVIpcBasePacket< HousingWardInfo >
{
uint16_t unknown1;
uint16_t wardId;
uint16_t territoryTypeId;
uint16_t unknown2;
struct HouseInfoEntry
{
uint32_t housePrice;
uint8_t infoFlags;
Common::HousingAppeal houseAppeal[3];
char estateOwnerName[30];
} houseInfoEntry[60];
};
/** /**
* Structural representation of the packet sent by the server * Structural representation of the packet sent by the server
* to show the current shared estate settings * to show the current shared estate settings

View file

@ -1,52 +0,0 @@
#include <ScriptObject.h>
#include <Actor/Player.h>
#define ACTION_ATTUNE 0x13
#define AetheryteBaseId 0x50000
#define AETHERYTE_MENU_AETHERNET 1
#define AETHERYTE_MENU_HOUSING 2
#define AETHERYTE_MENU_HOME_POINT 3
#define AETHERYTE_MENU_FAVORITE_POINT 4
#define AETHERYTE_MENU_FAVORITE_POINT_SECURITY_TOKEN 5
using namespace Core;
class Aethernet :
public Sapphire::ScriptAPI::EventScript
{
public:
Aethernet() :
Sapphire::ScriptAPI::EventScript( EVENTSCRIPT_AETHERNET_ID )
{
}
void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override
{
if( player.isAetheryteRegistered( eventId & 0xFFFF ) )
{
player.playScene( eventId, 2, 0, []( Entity::Player& player, const Event::SceneResult& result )
{
if( result.param1 == 256 )
{
player.teleport( result.param2, 2 );
}
} );
}
else
{
player.eventActionStart( eventId, ACTION_ATTUNE,
[]( Entity::Player& player, uint32_t eventId, uint64_t additional )
{
player.registerAetheryte( eventId & 0xFFFF );
player.playScene( eventId, 3, 0, 0, 0 );
},
[]( Entity::Player& ply, uint32_t evntId, uint64_t additional )
{
}, 0 );
}
}
};

View file

@ -1,33 +1,65 @@
#include <ScriptObject.h> #include <ScriptObject.h>
#include <Actor/Player.h> #include <Actor/Player.h>
#include <Framework.h>
#include <Exd/ExdDataGenerated.h>
#define ACTION_ATTUNE 0x13
#define ACTION_TELEPORT 0x4
#define AetheryteBaseId 0x50000
#define AETHERYTE_MENU_AETHERNET 1
#define AETHERYTE_MENU_HOUSING 2
#define AETHERYTE_MENU_HOME_POINT 3
#define AETHERYTE_MENU_FAVORITE_POINT 4
#define AETHERYTE_MENU_FAVORITE_POINT_SECURITY_TOKEN 5
using namespace Core; using namespace Core;
class Aetheryte : class Aetheryte :
public Sapphire::ScriptAPI::EventScript public Sapphire::ScriptAPI::EventScript
{ {
private:
constexpr static auto ACTION_ATTUNE = 0x13;
constexpr static auto ACTION_TELEPORT = 0x4;
constexpr static auto AETHERYTE_MENU_AETHERNET = 1;
constexpr static auto AETHERYTE_MENU_HOUSING = 2;
constexpr static auto AETHERYTE_MENU_HOME_POINT = 3;
constexpr static auto AETHERYTE_MENU_FAVORITE_POINT = 4;
constexpr static auto AETHERYTE_MENU_FAVORITE_POINT_SECURITY_TOKEN = 5;
public: public:
Aetheryte() : Aetheryte() :
Sapphire::ScriptAPI::EventScript( EVENTSCRIPT_AETHERYTE_ID ) Sapphire::ScriptAPI::EventScript( 0x00050000 )
{ {
} }
void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override void aethernet( uint32_t eventId, Entity::Player& player, uint64_t actorId )
{ {
if( player.isAetheryteRegistered( eventId & 0xFFFF ) ) if( player.isAetheryteRegistered( eventId & 0xFFFF ) )
{ {
player.playScene( eventId, 0, 1, []( Entity::Player& player, const Event::SceneResult& result ) player.playScene( eventId, 2, 0, [this]( Entity::Player& player, const Event::SceneResult& result )
{
if( result.param1 == 256 )
{
player.teleport( result.param2, 2 );
}
} );
}
else
{
player.eventActionStart( eventId, ACTION_ATTUNE,
[]( Entity::Player& player, uint32_t eventId, uint64_t additional )
{
player.registerAetheryte( eventId & 0xFFFF );
player.playScene( eventId, 3, 0, 0, 0 );
},
[]( Entity::Player& ply, uint32_t evntId, uint64_t additional )
{
}, 0 );
}
}
void aetheryte( uint32_t eventId, Entity::Player& player, uint64_t actorId )
{
if( player.isAetheryteRegistered( eventId & 0xFFFF ) )
{
player.playScene( eventId, 0, 1, [this]( Entity::Player& player, const Event::SceneResult& result )
{ {
if( result.param1 == 256 ) // set homepoint if( result.param1 == 256 ) // set homepoint
{ {
@ -55,7 +87,7 @@ public:
else else
{ {
player.eventActionStart( eventId, ACTION_ATTUNE, player.eventActionStart( eventId, ACTION_ATTUNE,
[]( Entity::Player& player, uint32_t eventId, uint64_t additional ) [this]( Entity::Player& player, uint32_t eventId, uint64_t additional )
{ {
player.registerAetheryte( eventId & 0xFFFF ); player.registerAetheryte( eventId & 0xFFFF );
@ -73,4 +105,20 @@ public:
{}, 0 ); {}, 0 );
} }
} }
void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override
{
auto pExdData = getFramework()->get< Core::Data::ExdDataGenerated >();
if( !pExdData )
return;
auto aetherInfo = pExdData->get< Core::Data::Aetheryte >( eventId & 0xFFFF );
if( !aetherInfo )
return;
if( aetherInfo->isAetheryte )
aetheryte( eventId, player, actorId );
else
aethernet( eventId, player, actorId );
}
}; };

View file

@ -8,7 +8,7 @@ class GilShop :
{ {
public: public:
GilShop() : GilShop() :
Sapphire::ScriptAPI::EventScript( 0x00040001 ) Sapphire::ScriptAPI::EventScript( 0x00040000 )
{ {
} }

View file

@ -2,6 +2,9 @@
#include <Actor/Player.h> #include <Actor/Player.h>
#include <Exd/ExdDataGenerated.h> #include <Exd/ExdDataGenerated.h>
#include <Zone/TerritoryMgr.h>
#include <Zone/HousingMgr.h>
#include <Zone/ZonePosition.h>
#include <Framework.h> #include <Framework.h>
using namespace Core; using namespace Core;
@ -16,35 +19,75 @@ public:
void inner( Entity::Player& player, const Event::SceneResult& result ) void inner( Entity::Player& player, const Event::SceneResult& result )
{ {
if( result.param1 != 256 ) if( result.param1 == 256 ) // exit
{ {
std::function< void( Entity::Player&, const Event::SceneResult& ) > fn = std::bind( &WarpTaxi::inner, this, std::placeholders::_1, std::placeholders::_2 ); player.eventFinish( 1310721, 0 );
player.eventFinish( getId(), 1 );
}
else if( result.param1 == 768 ) // teleport to ward
{
player.eventFinish( 1310721, 0 );
player.eventFinish( getId(), 1 );
player.playScene( 1310721, 0, HIDE_HOTBAR, 0, 1, 341, fn ); // todo: this is shit, move to housingmgr? handle moving players in and out of it there?
auto exdData = getFramework()->get< Core::Data::ExdDataGenerated >();
auto warp = exdData->get< Core::Data::Warp >( getId() );
if( !warp )
return;
auto level = exdData->get< Core::Data::Level >( warp->level );
if( !level )
{
// fetch from cache
auto teriMgr = getFramework()->get< Core::TerritoryMgr >();
auto pos = teriMgr->getTerritoryPosition( warp->level );
if( !pos )
return;
// lookup instance
auto housingMgr = getFramework()->get< Core::HousingMgr >();
auto landSetId = housingMgr->toLandSetId( 341, result.param3 );
auto hZone = housingMgr->getHousingZoneByLandSetId( landSetId );
if( !hZone )
return;
player.setPos( pos->getTargetPosition() );
player.setRot( pos->getTargetRotation() );
player.setInstance( hZone );
}
}
else
{
player.playScene( 1310721, 0, HIDE_HOTBAR, 0, 1, 341, std::bind( &WarpTaxi::inner, this, std::placeholders::_1, std::placeholders::_2 ) );
} }
} }
void inner2( Entity::Player& player, uint64_t actorId ) void inner2( Entity::Player& player, uint64_t actorId )
{ {
player.eventStart( actorId, 1310721, Event::EventHandler::Nest, 0, 0 ); player.playScene( getId(), 0, HIDE_HOTBAR, 0, 0, 32529, [this, actorId]( Entity::Player& player, const Event::SceneResult& result )
std::function< void( Entity::Player&, const Event::SceneResult& ) > fn = std::bind( &WarpTaxi::inner, this, std::placeholders::_1, std::placeholders::_2 ); {
player.playScene( 1310721, 0, HIDE_HOTBAR, 0, 1, 341, fn ); player.eventStart( actorId, 1310721, Event::EventHandler::Nest, 1, 0 );
player.playScene( 1310721, 0, HIDE_HOTBAR, 0, 1, 341, std::bind( &WarpTaxi::inner, this, std::placeholders::_1, std::placeholders::_2 ) );
} );
} }
void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override void onTalk( uint32_t eventId, Entity::Player& player, uint64_t actorId ) override
{ {
auto exddata = getFramework()->get< Core::Data::ExdDataGenerated >(); auto exdData = getFramework()->get< Core::Data::ExdDataGenerated >();
if( !exddata ) if( !exdData )
return; return;
auto warp = exddata->get< Core::Data::Warp >( eventId ); auto warp = exdData->get< Core::Data::Warp >( eventId );
if( !warp ) if( !warp )
return; return;
player.eventStart( actorId, warp->defaultTalk1, Event::EventHandler::Nest, 0, 0, std::bind( &WarpTaxi::inner2, this, std::placeholders::_1, std::placeholders::_2 ) ); player.eventStart( actorId, warp->defaultTalk1, Event::EventHandler::Nest, 0, 0, std::bind( &WarpTaxi::inner2, this, std::placeholders::_1, std::placeholders::_2 ) );
player.playScene( warp->defaultTalk1, 0, HIDE_HOTBAR, [warp, this]( Entity::Player& player, const Event::SceneResult& result ) player.playScene( warp->defaultTalk1, 0, HIDE_HOTBAR, 0, 0, 7, nullptr );
{
} );
} }
}; };

View file

@ -77,10 +77,10 @@ std::string Core::Event::getEventName( uint32_t eventId )
case Event::EventHandler::EventHandlerType::Shop: case Event::EventHandler::EventHandlerType::Shop:
{ {
auto shopInfo = pExdData->get< Core::Data::GilShop >( eventId ); auto shopInfo = pExdData->get< Core::Data::GilShop >( eventId );
std::string name = shopInfo->name;
if( shopInfo ) if( shopInfo )
return name; return shopInfo->name;
return unknown + "GilShop"; return unknown + "GilShop";
} }
default: default:

View file

@ -344,6 +344,16 @@ void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVAR
pHousingMgr->sendLandSignOwned( player, ward, plot, territoryId ); pHousingMgr->sendLandSignOwned( player, ward, plot, territoryId );
break; break;
} }
case ClientTriggerType::RequestWardLandInfo:
{
auto pHousingMgr = g_fw.get< HousingMgr >();
if( !pHousingMgr )
break;
pHousingMgr->sendWardLandInfo( player, param12, param11 );
break;
}
case ClientTriggerType::RequestLandRelinquish: case ClientTriggerType::RequestLandRelinquish:
{ {
auto plot = static_cast< uint8_t >( param12 & 0xFF ); auto plot = static_cast< uint8_t >( param12 & 0xFF );
@ -354,7 +364,7 @@ void Core::Network::GameConnection::clientTriggerHandler( const Packets::FFXIVAR
} }
case ClientTriggerType::RequestEstateRename: case ClientTriggerType::RequestEstateRename:
{ {
// removed temporarly, there is no such thing as a LandName // removed temporarly, there is no such thing as a LandName
/* auto landRenamePacket = makeZonePacket< Server::FFXIVIpcLandRename >( player.getId() ); /* auto landRenamePacket = makeZonePacket< Server::FFXIVIpcLandRename >( player.getId() );
uint8_t ward = ( param12 & 0xFF00 ) >> 8; uint8_t ward = ( param12 & 0xFF00 ) >> 8;

View file

@ -456,7 +456,7 @@ void Core::Network::GameConnection::gm1Handler( const Packets::FFXIVARR_PACKET_R
player.sendUrgent( "No zone instance found for " + std::to_string( param1 ) ); player.sendUrgent( "No zone instance found for " + std::to_string( param1 ) );
break; break;
} }
if( !pTeriMgr->isDefaultTerritory( param1 ) ) if( !pTeriMgr->isDefaultTerritory( param1 ) )
{ {
player.sendUrgent( pZone->getName() + " is an instanced area - instance ID required to zone in." ); player.sendUrgent( pZone->getName() + " is an instanced area - instance ID required to zone in." );
@ -503,6 +503,15 @@ void Core::Network::GameConnection::gm1Handler( const Packets::FFXIVARR_PACKET_R
} }
break; break;
} }
case GmCommand::Kick:
{
// todo: this doesn't kill their session straight away, should do this properly but its good for when you get stuck for now
targetPlayer->setMarkedForRemoval();
player.sendNotice( "Kicked " + targetPlayer->getName() );
break;
}
case GmCommand::TeriInfo: case GmCommand::TeriInfo:
{ {
auto pCurrentZone = player.getCurrentZone(); auto pCurrentZone = player.getCurrentZone();

View file

@ -10,11 +10,6 @@
#define EXPORT __attribute__((visibility("default"))) #define EXPORT __attribute__((visibility("default")))
#endif #endif
// todo: this is shit
// constant script ids for certain events
#define EVENTSCRIPT_AETHERYTE_ID 0x50000
#define EVENTSCRIPT_AETHERNET_ID 0x50001
namespace Core namespace Core
{ {
class Framework; class Framework;
@ -56,14 +51,14 @@ namespace Sapphire::ScriptAPI
/*! /*!
* @brief Sets the ptr to the framework for use inside scripts * @brief Sets the ptr to the framework for use inside scripts
* *
* @param fw The ptr to g_fw (Core::Framework) * @param fw The ptr to g_fw (Core::Framework)
*/ */
virtual void setFramework( Core::Framework* fw ); virtual void setFramework( Core::Framework* fw );
/*! /*!
* @brief Returns the current ptr to framework set for the current script * @brief Returns the current ptr to framework set for the current script
* *
* @return A pointer to Core::Framework * @return A pointer to Core::Framework
*/ */
virtual Core::Framework* getFramework() const; virtual Core::Framework* getFramework() const;

View file

@ -168,29 +168,22 @@ void Core::Scripting::ScriptMgr::onPlayerFirstEnterWorld( Entity::Player& player
bool Core::Scripting::ScriptMgr::onTalk( Entity::Player& player, uint64_t actorId, uint32_t eventId ) bool Core::Scripting::ScriptMgr::onTalk( Entity::Player& player, uint64_t actorId, uint32_t eventId )
{ {
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::EventScript >( eventId & 0xFFFF0000 );
auto pExdData = g_fw.get< Data::ExdDataGenerated >(); if( script )
uint16_t eventType = eventId >> 16;
uint32_t scriptId = eventId;
// todo: replace this shit with something more flexible allowing for handlers for an entire type without a bunch of if statements
// aethernet/aetherytes need to be handled separately
if( eventType == Event::EventHandler::EventHandlerType::Aetheryte )
{ {
auto aetherInfo = pExdData->get< Core::Data::Aetheryte >( eventId & 0xFFFF ); script->onTalk( eventId, player, actorId );
scriptId = EVENTSCRIPT_AETHERYTE_ID; return true;
if( !aetherInfo->isAetheryte )
scriptId = EVENTSCRIPT_AETHERNET_ID;
} }
else if( eventType == Event::EventHandler::EventHandlerType::Shop ) else
{ {
scriptId = 0x00040001; auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::EventScript >( eventId );
if( !script )
return false;
script->onTalk( eventId, player, actorId );
return true;
} }
auto script = m_nativeScriptMgr->getScript< Sapphire::ScriptAPI::EventScript >( scriptId );
if( !script )
return false;
script->onTalk( eventId, player, actorId );
return true; return true;
} }

View file

@ -133,17 +133,17 @@ Core::LandPurchaseResult Core::HousingMgr::purchaseLand( Entity::Player& player,
if( pLand->getState() != HouseState::forSale ) if( pLand->getState() != HouseState::forSale )
return LandPurchaseResult::ERR_NOT_AVAILABLE; return LandPurchaseResult::ERR_NOT_AVAILABLE;
if( gilAvailable < plotPrice ) if( gilAvailable < plotPrice )
return LandPurchaseResult::ERR_NOT_ENOUGH_GIL; return LandPurchaseResult::ERR_NOT_ENOUGH_GIL;
switch( static_cast< LandPurchaseMode >( state ) ) switch( static_cast< LandPurchaseMode >( state ) )
{ {
case LandPurchaseMode::FC: case LandPurchaseMode::FC:
player.sendDebug( "Free company house purchase aren't supported at this time." ); player.sendDebug( "Free company house purchase aren't supported at this time." );
return LandPurchaseResult::ERR_INTERNAL; return LandPurchaseResult::ERR_INTERNAL;
case LandPurchaseMode::PRIVATE: case LandPurchaseMode::PRIVATE:
{ {
@ -169,11 +169,11 @@ Core::LandPurchaseResult Core::HousingMgr::purchaseLand( Entity::Player& player,
pHousing->sendLandUpdate( plot ); pHousing->sendLandUpdate( plot );
return LandPurchaseResult::SUCCESS; return LandPurchaseResult::SUCCESS;
} }
default: default:
return LandPurchaseResult::ERR_INTERNAL; return LandPurchaseResult::ERR_INTERNAL;
} }
} }
bool Core::HousingMgr::relinquishLand( Entity::Player& player, uint8_t plot ) bool Core::HousingMgr::relinquishLand( Entity::Player& player, uint8_t plot )
@ -203,3 +203,50 @@ bool Core::HousingMgr::relinquishLand( Entity::Player& player, uint8_t plot )
return true; return true;
} }
void Core::HousingMgr::sendWardLandInfo( Entity::Player& player, uint8_t wardId, uint16_t territoryTypeId )
{
auto landSetId = toLandSetId( territoryTypeId, wardId );
auto hZone = getHousingZoneByLandSetId( landSetId );
if( !hZone )
return;
auto wardInfoPacket = makeZonePacket< Server::FFXIVIpcHousingWardInfo >( player.getId() );
wardInfoPacket->data().wardId = wardId;
wardInfoPacket->data().territoryTypeId = territoryTypeId;
for( int i = 0; i < 60; i++ )
{
auto land = hZone->getLand( i );
assert( land );
auto& entry = wardInfoPacket->data().houseInfoEntry[ i ];
entry.housePrice = land->getCurrentPrice();
switch( land->getLandType() )
{
case LandType::FreeCompany:
entry.infoFlags = Common::WardEstateFlags::IsEstateOwned | Common::WardEstateFlags::IsFreeCompanyEstate;
// todo: send FC name
break;
case LandType::Private:
entry.infoFlags = Common::WardEstateFlags::IsEstateOwned;
auto owner = land->getPlayerOwner();
std::string playerName = g_fw.get< Core::ServerZone >()->getPlayerNameFromDb( owner );
memcpy( &entry.estateOwnerName, playerName.c_str(), playerName.size() );
break;
}
// todo: check we have an estate message and set the flag
// todo: check if estate allows public entry
}
player.queuePacket( wardInfoPacket );
}

View file

@ -30,6 +30,8 @@ namespace Core
void sendLandSignFree( Entity::Player& player, uint8_t wardId, uint8_t plotId, uint16_t territoryTypeId ); void sendLandSignFree( Entity::Player& player, uint8_t wardId, uint8_t plotId, uint16_t territoryTypeId );
LandPurchaseResult purchaseLand( Entity::Player& player, uint8_t plot, uint8_t state ); LandPurchaseResult purchaseLand( Entity::Player& player, uint8_t plot, uint8_t state );
void sendWardLandInfo( Entity::Player& player, uint8_t wardId, uint16_t territoryTypeId );
bool relinquishLand( Entity::Player& player, uint8_t plot ); bool relinquishLand( Entity::Player& player, uint8_t plot );
private: private:

View file

@ -127,6 +127,7 @@ int main()
result += generateEnum( "Tribe", 0, "uint8_t" ); result += generateEnum( "Tribe", 0, "uint8_t" );
result += generateEnum( "Town", 0, "uint8_t" ); result += generateEnum( "Town", 0, "uint8_t" );
result += generateEnum( "Weather", 1, "uint8_t" ); result += generateEnum( "Weather", 1, "uint8_t" );
result += generateEnum( "HosuingAppeal", 0, "uint8_t" );
result += "}\n"; result += "}\n";
result += "}\n#endif\n"; result += "}\n#endif\n";
g_log.info( result ); g_log.info( result );