Mercurial > hg > openttd
changeset 8544:50768dea0a8b draft
(svn r12122) -Codechange: Add framework for generic feature callbacks, along with some parts for AI use.
author | peter1138 <peter1138@openttd.org> |
---|---|
date | Tue, 12 Feb 2008 13:23:57 +0000 |
parents | de271daa833c |
children | e13ff026f5df |
files | projects/openttd_vs80.vcproj projects/openttd_vs90.vcproj source.list src/newgrf.cpp src/newgrf_generic.cpp src/newgrf_generic.h src/newgrf_spritegroup.h |
diffstat | 7 files changed, 257 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -1072,6 +1072,10 @@ > </File> <File + RelativePath=".\..\src\newgrf_generic.h" + > + </File> + <File RelativePath=".\..\src\newgrf_house.h" > </File> @@ -1948,6 +1952,10 @@ > </File> <File + RelativePath=".\..\src\newgrf_generic.cpp" + > + </File> + <File RelativePath=".\..\src\newgrf_house.cpp" > </File>
--- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -1069,6 +1069,10 @@ > </File> <File + RelativePath=".\..\src\newgrf_generic.h" + > + </File> + <File RelativePath=".\..\src\newgrf_house.h" > </File> @@ -1945,6 +1949,10 @@ > </File> <File + RelativePath=".\..\src\newgrf_generic.cpp" + > + </File> + <File RelativePath=".\..\src\newgrf_house.cpp" > </File>
--- a/source.list +++ b/source.list @@ -176,6 +176,7 @@ newgrf_commons.h newgrf_config.h newgrf_engine.h +newgrf_generic.h newgrf_house.h newgrf_industries.h newgrf_industrytiles.h @@ -405,6 +406,7 @@ newgrf_commons.cpp newgrf_config.cpp newgrf_engine.cpp +newgrf_generic.cpp newgrf_house.cpp newgrf_industries.cpp newgrf_industrytiles.cpp
--- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -3089,6 +3089,11 @@ * W cid cargo ID (sprite group ID) for this type of cargo * W def-cid default cargo ID (sprite group ID) */ + if (_cur_grffile->spritegroups == 0) { + grfmsg(1, "FeatureMapSpriteGroup: No sprite groups to work on! Skipping"); + return; + } + if (!check_length(len, 6, "FeatureMapSpriteGroup")) return; uint8 feature = buf[1]; @@ -3099,7 +3104,12 @@ /* If idcount is zero, this is a feature callback */ if (idcount == 0) { - grfmsg(2, "FeatureMapSpriteGroup: Feature callbacks not implemented yet"); + byte *bp = &buf[4]; + uint16 groupid = grf_load_word(&bp); + + grfmsg(6, "FeatureMapSpriteGroup: Adding generic feature callback for feature %d", feature); + + AddGenericCallback(feature, _cur_grffile, _cur_grffile->spritegroups[groupid]); return; } @@ -3109,11 +3119,6 @@ grfmsg(6, "FeatureMapSpriteGroup: Feature %d, %d ids, %d cids, wagon override %d", feature, idcount, cidcount, wagover); - if (_cur_grffile->spritegroups == 0) { - grfmsg(1, "FeatureMapSpriteGroup: No sprite groups to work on! Skipping"); - return; - } - switch (feature) { case GSF_TRAIN: case GSF_ROAD: @@ -5101,6 +5106,9 @@ UnloadCustomEngineSprites(); ResetEngineListOrder(); + /* Reset generic feature callback lists */ + ResetGenericCallbacks(); + /* Reset price base data */ ResetPriceBaseMultipliers();
new file mode 100644 --- /dev/null +++ b/src/newgrf_generic.cpp @@ -0,0 +1,179 @@ +/* $Id$ */ + +#include "stdafx.h" +#include "openttd.h" +#include "variables.h" +#include "landscape.h" +#include "debug.h" +#include "newgrf.h" +#include "newgrf_callbacks.h" +#include "newgrf_commons.h" +#include "newgrf_spritegroup.h" +#include "newgrf_generic.h" +#include "tile_map.h" +#include <list> + + +struct GenericCallback { + const GRFFile *file; + const SpriteGroup *group; + + GenericCallback(const GRFFile *file, const SpriteGroup *group) : + file(file), + group(group) + { } +}; + +typedef std::list<GenericCallback> GenericCallbackList; + +static GenericCallbackList _gcl[GSF_END]; + + +/** + * Reset all generic feature callback sprite groups. + */ +void ResetGenericCallbacks() +{ + for (uint8 feature = 0; feature < lengthof(_gcl); feature++) { + _gcl[feature].clear(); + } +} + + +/** + * Add a generic feature callback sprite group to the appropriate feature list. + * @param feature + * @param file + * @param group + */ +void AddGenericCallback(uint8 feature, const GRFFile *file, const SpriteGroup *group) +{ + if (feature >= lengthof(_gcl)) { + grfmsg(5, "AddGenericCallback: Unsupported feature 0x%02X", feature); + return; + } + + /* Generic feature callbacks are evaluated in reverse (i.e. the last group + * to be added is evaluated first, etc) thus we push the group to the + * beginning of the list so a standard iterator will do the right thing. */ + _gcl[feature].push_front(GenericCallback(file, group)); +} + + +static uint32 GenericCallbackGetRandomBits(const ResolverObject *object) +{ + return 0; +} + + +static uint32 GenericCallbackGetTriggers(const ResolverObject *object) +{ + return 0; +} + + +static void GenericCallbackSetTriggers(const ResolverObject *object, int triggers) +{ + return; +} + + +static uint32 GenericCallbackGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) +{ + switch (variable) { + case 0x40: return object->u.generic.cargo_type; + + case 0x80: return object->u.generic.cargo_type; + case 0x81: return object->u.generic.cargo_type; + case 0x82: return object->u.generic.default_selection; + case 0x83: return object->u.generic.src_industry; + case 0x84: return object->u.generic.dst_industry; + case 0x85: return object->u.generic.distance; + case 0x86: return object->u.generic.event; + case 0x87: return object->u.generic.count; + case 0x88: return object->u.generic.station_size; + + default: break; + } + + DEBUG(grf, 1, "Unhandled generic feature property 0x%02X", variable); + + *available = false; + return 0; +} + + +static const SpriteGroup *GenericCallbackResolveReal(const ResolverObject *object, const SpriteGroup *group) +{ + if (group->g.real.num_loaded == 0) return NULL; + + return group->g.real.loaded[0]; +} + + +static inline void NewGenericResolver(ResolverObject *res) +{ + res->GetRandomBits = &GenericCallbackGetRandomBits; + res->GetTriggers = &GenericCallbackGetTriggers; + res->SetTriggers = &GenericCallbackSetTriggers; + res->GetVariable = &GenericCallbackGetVariable; + res->ResolveReal = &GenericCallbackResolveReal; + + res->callback = CBID_NO_CALLBACK; + res->callback_param1 = 0; + res->callback_param2 = 0; + res->last_value = 0; + res->trigger = 0; + res->reseed = 0; +} + + +/** Follow a generic feature callback list and return the first successful + * answer + * @param feature GRF Feature of callback + * @param object pre-populated resolver object + * @param file address of GRFFile object if file reference is needed, NULL is valid + * @return callback value if successful or CALLBACK_FAILED + */ +static uint16 GetGenericCallbackResult(uint8 feature, ResolverObject *object, const GRFFile **file) +{ + assert(feature < lengthof(_gcl)); + + /* Test each feature callback sprite group. */ + for (GenericCallbackList::const_iterator it = _gcl[feature].begin(); it != _gcl[feature].end(); ++it) { + const SpriteGroup *group = it->group; + group = Resolve(group, object); + if (group == NULL || group->type != SGT_CALLBACK) continue; + + /* Return NewGRF file if necessary */ + if (file != NULL) *file = it->file; + + return group->g.callback.result; + } + + /* No callback returned a valid result, so we've failed. */ + return CALLBACK_FAILED; +} + + +/** + * 'Execute' an AI purchase selection callback + */ +uint16 GetAiPurchaseCallbackResult(uint8 feature, CargoID cargo_type, uint8 default_selection, IndustryType src_industry, IndustryType dst_industry, uint8 distance, AIConstructionEvent event, uint8 count, uint8 station_size, const GRFFile **file) +{ + ResolverObject object; + + NewGenericResolver(&object); + + object.callback = CBID_GENERIC_AI_PURCHASE_SELECTION; + object.u.generic.cargo_type = cargo_type; + object.u.generic.default_selection = default_selection; + object.u.generic.src_industry = src_industry; + object.u.generic.dst_industry = dst_industry; + object.u.generic.distance = distance; + object.u.generic.event = event; + object.u.generic.count = count; + object.u.generic.station_size = station_size; + + return GetGenericCallbackResult(feature, &object, file); +}
new file mode 100644 --- /dev/null +++ b/src/newgrf_generic.h @@ -0,0 +1,35 @@ +/* $Id$ */ + +#ifndef NEWGRF_GENERIC_H +#define NEWGRF_GENERIC_H + +enum AIConstructionEvent { + AICE_TRAIN_CHECK_RAIL_ENGINE = 0x00, ///< Check if we should build an engine + AICE_TRAIN_CHECK_ELRAIL_ENGINE = 0x01, + AICE_TRAIN_CHECK_MONORAIL_ENGINE = 0x02, + AICE_TRAIN_CHECK_MAGLEV_ENGINE = 0x03, + AICE_TRAIN_GET_RAIL_WAGON = 0x08, + AICE_TRAIN_GET_ELRAIL_WAGON = 0x09, + AICE_TRAIN_GET_MONORAIL_WAGON = 0x0A, + AICE_TRAIN_GET_MAGLEV_WAGON = 0x0B, + AICE_TRAIN_GET_RAILTYPE = 0x0F, + + AICE_ROAD_CHECK_ENGINE = 0x00, ///< Check if we should build an engine + AICE_ROAD_GET_FIRST_ENGINE = 0x01, ///< Unused, we check all + AICE_ROAD_GET_NUMBER_ENGINES = 0x02, ///< Unused, we check all + + AICE_SHIP_CHECK_ENGINE = 0x00, ///< Check if we should build an engine + AICE_SHIP_GET_FIRST_ENGINE = 0x01, ///< Unused, we check all + AICE_SHIP_GET_NUMBER_ENGINES = 0x02, ///< Unused, we check all + + AICE_AIRCRAFT_CHECK_ENGINE = 0x00, ///< Check if we should build an engine + + AICE_STATION_GET_STATION_ID = 0x00, ///< Get a station ID to build +}; + +void ResetGenericCallbacks(); +void AddGenericCallback(uint8 feature, const struct GRFFile *file, const struct SpriteGroup *group); + +uint16 GetAiPurchaseCallbackResult(uint8 feature, CargoID cargo_type, uint8 default_selection, IndustryType src_industry, IndustryType dst_industry, uint8 distance, AIConstructionEvent event, uint8 count, uint8 station_size, const struct GRFFile **file); + +#endif /* NEWGRF_GENERIC_H */
--- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -10,6 +10,7 @@ #include "newgrf_storage.h" #include "core/bitmath_func.hpp" #include "gfx_type.h" +#include "newgrf_generic.h" /** * Gets the value of a so-called newgrf "register". @@ -236,6 +237,16 @@ struct { const struct CargoSpec *cs; } cargo; + struct { + CargoID cargo_type; + uint8 default_selection; + IndustryType src_industry; + IndustryType dst_industry; + uint8 distance; + AIConstructionEvent event; + uint8 count; + uint8 station_size; + } generic; } u; uint32 (*GetRandomBits)(const struct ResolverObject*);