-
Notifications
You must be signed in to change notification settings - Fork 1
SRD: Registration Functions
This page provides an overview of Spellforce Framework functions which are used to allow the Spellforce Framework to register, monitor and terminate all active spells in the game world, and also modify their behavior by linking them to custom game logic.
These functions are taken from the sf_registration_functions.h header file. Please, note that you don't need to include that header in your project. It is automatically included as part of the sfsf.h general interface.
This page is up-to date for version of the Spellforce Framework 1.02-beta.
Below listed all functions you can find in sf_registration_functions.h. The registration functions can be accessed using registrationAPI-> prefix, provided this group was previously initialized. In order to initialize the registration functions you should,
-
Initialize a pointer to registration functions within the global scope of your project. This is done as follows:
RegistrationFunctions *registrationAPI; -
Assign this pointer the address of the registration functions within the main structure of the Spellforce Framework. Usually this is done as part of
InitModulefunction after the framework was initialized. This is done in the following way:registrationAPI = sfsf->registrationAPI;
This function is necessary to implement special spell logic such as Aura, Summon, Domination, Chain or On-Hit. It assigns a tag to the spell that modifies its behavior accordingly. This function is not needed for spells with other logic. The full list of possible tags can be seen here.
Parameters:
Spell: Pointer to the SFSpell structure representing the spell.
Spell Tag: The tag alternating a spell's behavior via assigning the spell to a broader group of spells which share the same core logic.
Function Signature:
void applySpellTag(SFSpell *spell, SpellTag tag);Example Usage:
registrationAPI->applySpellTag(arrows_reflection_spell, TARGET_ONHIT_SPELL);This function is used to link an AOE spell to its AI handler. This handler will be automatically triggered whenever a unit possessing this spell considers using it against a single target or against a group of enemies. The handler allows to tune unit behavior depending on under what circumstances the spell must be used.
Parameters:
Spell: Pointer to the SFSpell structure representing the spell.
Handler: Pointer to the AOE AI handler function.
Function Signature:
void linkAOEAIHandler(SFSpell *spell, ai_aoe_handler_ptr handler);Example Usage:
registrationAPI->linkAOEAIHandler(shield_wall_universal_spell, &shield_wall_universal_ai_aoe_handler);This function is used to link the spell to its Avoidance AI handler. This handler is automatically triggered whenever a unit possessing specific spell gets engaged into melee combat. This handler can be used to make the unit put on a defensive spell when it's just time or somehow avoid combat.
Parameters:
Spell: Pointer to the SFSpell structure representing the spell.
Handler: Pointer to the Spell Refresh handler function.
Function Signature:
void linkAvoidanceAIHandler(SFSpell *spell, ai_avoidance_handler_ptr handler);Example Usage:
registrationAPI->linkAvoidanceAIHandler(invulnerability, &sf_ai_avoidance_invulnerability_handler);This function is used to link the building type with the building handler which is triggered at the moment when the building construction is finished. For example, this handler is used to attach units to watchtowers.
Parameters:
building: The pointer to the custom building type registered within the Spellforce Framework.
handler: Pointer to the Building Done Handler function.
Function Signature:
void linkBuildingDoneHandler(SFBuilding *building, building_done_handler_ptr handler);Example Usage:
registrationAPI->linkBuildingDoneHandler(dwarf_tower, &dwarf_hammer_tower_done_handler);This function makes the game load the building game data from the json file.
Note: it is unreliable to add new buildings through GameData.cff, because the number of building types the game engine can load from it is hardcoded to be 213.
Note: Building slot 35, 50, 54, 97, 101, 105 are free.
Building slot 37 is registered for "Elf Druid Guild" but remains unused too. It is race 3 (playable elf), but has no model bar placeholder archer tower.
Because the most of slots are taken by vanilla buildings, it's better to keep custom buildings as separate json files stored within the mod folder.
Parameters:
building: The pointer to the custom building type registered within the Spellforce Framework.
json_name: The json filename which contains building parameters such as health, resource costs, faction and defines building collisions.
The building data must be placed in sfsf/%modname%/buildings/ folder. It must be file of .json extension.
The filename must be passed as argument without extenstion (w/o .json).
Function Signature:
void linkBuildingJSON(SFBuilding *building, const char *building_json_name);Example Usage:
registrationAPI->linkBuildingJSON(dwarf_tower, "dwarf_tower_hammer");This functions is used to link a spell to its Deal Damage handler. This handler is triggered whenever the target affected by this spell takes damage. The Phase parameter will determine the exact moment when this handler is triggered: before or after damage is applied.
Parameters:
Spell: Pointer to the SFSpell structure representing the spell.
Handler: Pointer to the Deal Damage handler function.
Phase: The damage phase of a spell when the Deal Damage handler must be triggered.
Function Signature:
void linkDealDamageHandler(SFSpell *spell, damage_handler_ptr handler, SpellDamagePhase phase);Example Usage:
registrationAPI->linkDealDamageHandler(interference_spell, &interference_deal_damage_handler, SpellDamagePhase::PRE);d This function is used to link a spell to the handler which implements its game logic.
Parameters:
Spell: Pointer to the SFSpell structure representing the spell.
Spell job index: The index used to link the spell with its spell logic.
Handler: Pointer to the Spell Effect handler function.
Function Signature:
void linkEffectHandler(SFSpell *spell, uint16_t spell_job_id, handler_ptr effectHandler);Example Usage:
registrationAPI->linkEffectHandler(shield_wall_spell, SHIELD_WALL_JOB, &shield_wall_effect_handler);This function is used to link a spell to its Spell End handler. This handler is automatically called by engine when the spell has to be stopped, but wasn't terminated as part of its game logic.
Parameters:
Spell: Pointer to the SFSpell structure representing the spell.
Handler: Pointer to the Spell End handler function.
Function Signature:
void linkEndHandler(SFSpell *spell, handler_ptr endHandler);Example Usage:
registrationAPI->linkEndHandler(ignite_spell, &ignite_spellend_handler);This function is used to link a spell to the On Hit handler. It is triggered whenever a creature makes a hit, given the creature is currently under the effect of a spell linked to this handler.
Alternatively, this handler gets triggered when the creature affected was hit, provided the spell behavior was alternated with applying the spell tag TARGET_ONHIT_SPELL.
The Phase parameter will determine the exact phase of the damage calculation when this handler is triggered.
Parameters:
Spell: Pointer to the SFSpell structure representing the spell.
Handler: Pointer to the On Hit handler function.
Phase: The hit phase when the On Hit handler must be triggered.
Function Signature:
void linkOnHitHandler(SFSpell *spell, onhit_handler_ptr onhitHandler, OnHitPhase phase);Example Usage:
registrationAPI->linkOnHitHandler(iceblade_spell, &iceblade_onhit_handler, PHASE_4);This function is used to link the spell to its Spell Refresh handler. The refresh handler is used to determine whether the target has already been affected by a previous instance of the same spell or by another spell that provides a similar effect that interferes with the effect we are going to apply to the affected target.
This handler is triggered with a wrapper function spellAPI->checkCanApply(*SF_CGdSpell, spell_index)(see here) which is typically called within a Spell Effect handler during the initial tick.
Parameters:
Spell: Pointer to the SFSpell structure representing the spell.
Handler: Pointer to the Spell Refresh handler function.
Function Signature:
void linkRefreshHandler(SFSpell *spell, refresh_handler_ptr handler);Example Usage:
registrationAPI->linkRefreshHandler(shield_wall_group_spell, &shield_wall_group_refresh_handler);This function is used to link the spell to its Spell Refresh handler. The refresh handler is used to determine whether the target has already been affected by a previous instance of the same spell or by another spell that provides a similar effect that interferes with the effect we are going to apply to the affected target.
This handler is triggered with a wrapper function spellAPI->checkCanApply(*SF_CGdSpell, spell_index)(see here) which is typically called within a Spell Effect handler during the initial tick.
Parameters:
Spell: Pointer to the SFSpell structure representing the spell.
Handler: Pointer to the Spell Refresh handler function.
Function Signature:
void linkRefreshHandler(SFSpell *spell, refresh_handler_ptr handler);Example Usage:
registrationAPI->linkRefreshHandler(shield_wall_group_spell, &shield_wall_group_refresh_handler);This function is used to link a spell to its Subeffect handler. This handler can be used to nest an additional logic within the main logic of a spell.
Parameters:
Spell: Pointer to the SFSpell structure representing the spell.
Handler: Pointer to the Spell Sub-effect handler function.
Function Signature:
void linkSubEffectHandler(SFSpell *spell, sub_effect_handler_ptr handler);Example Usage:
registrationAPI->linkSubEffectHandler(static_spell, &static_sub_effect_handler);This function is used to link a spell to a corresponding Spell Type handler. This handler is used to connect the instance of a spell corresponding to a specific Spell Type with its unique game logic known as Spell Job. Though most Spell Types possess distinct Spell Jobs, some Spell Types (first and foremost, governing aura spells) share the single Spell Job among each other.
Parameters:
Spell: Pointer to the SFSpell structure representing the spell.
Handler: Pointer to the Spell Type handler function.
Function Signature:
void linkTypeHandler(SFSpell *spell, handler_ptr typeHandler);Example Usage:
registrationAPI->linkTypeHandler(ignite_spell, &ignite_spelltype_handler);This function registers the building within the Spellforce Framework and makes the game engine acknowledge the custom building type.
This is another way of adding a custom building type, since the amount of slots for building types which are loaded from GameData.cff is hardcoded to be 213. Most of the slots there are occupied with vanilla buildings.
Note: Building slot 35, 50, 54, 97, 101, 105 are free.
Building slot 37 is registered for "Elf Druid Guild" but remains unused too. It is race 3 (playable elf), but has no model bar placeholder archer tower.
Parameters:
building_type: The index of custom building type represented as an integer in range 214-256. Numbers in range 1-213 are used by game engine, and shouldn't be to avoid conflicts.
Function Signature:
SFBuilding *registerBuilding(uint8_t building_type);Example Usage:
SFBuilding *dwarf_tower = registrationAPI->registerBuilding(214);This function registers the spell within the Spellforce Framework, making the spell visible for the framework. This means that whenever game event related to the spell occurs, the framework triggers the corresponding Spell handler, provided the handler was linked to the spell before.
This function should be used during the mod initialization, when other registration functions are applied also.
Parameters:
Spell: Pointer to the SFSpell structure representing the spell.
Spell type ID: The index used to determine type of the spell (e. g. Firebust, Pain, Healing).
Function Signature:
SFSpell *registerSpell(uint16_t spell_id);Example Usage:
// using fixed number
SFSpell *ignite_spell = registrationAPI->registerSpell(242);
// using predefined macro
SFSpell *shield_wall_spell = registrationAPI->registerSpell(SHIELD_WALL_LINE);The AI AOE handler is called when a unit sees at least one target, whether hostile or friendly. This handler allows the unit to decide whether to cast an AOE spell.
The handler provides Battle Development global object which acts as collection of lists of all figures and buildings in unit's sight, grouped by their relationship to the initial unit (ally, hostile). The handler also provides the target's position and the spell data of a spell that will be cast.
The handler must return an integer value that determines the priority of the spell in question. The value 0 stands for not casting the spell, 1 stands for the highest priority, and after that the higher value stands for the lower priority.
The function implementing the AOE AI handler should be declared as follows:
uint32_t __thiscall shield_wall_universal_ai_aoe_handler(SF_CGdBattleDevelopment *_this, SF_Coord *position, uint16_t spell_line, SF_CGdResourceSpell *spell_data)
{
return 1;
}The full list of vanilla AOE AI handlers can be checked here.
The Avoidance AI handler gets called when a unit possessing the spell becomes engaged in a melee combat. This handler controls such vanilla spells as Invulnerability, Hypnotize, Fire Shield, Ice Shield, Petrify, etc. It can be used to make the unit apply defensive spell in time, negate the hostile situation or escape it in some peculiar way.
The handler must return an integer value that determines the priority of the spell in question. The value 0 stands for not casting the spell, 1 stands for the highest priority, and after that the higher value stands for the lower priority.
The function implementing the Avoidance AI handler should be declared as follows:
uint32_t __thiscall sf_ai_avoidance_invulnerability_handler(CGdAIBattleData *_this, uint16_t figure_index, uint16_t spell_index)
{
return 250;
}The full list of vanilla Avoidance AI handlers can be checked here.
The Building Done handler is called at the moment when the building construction is finished. It can be used for various purposes: for example to initialize some of building XData or to attach a garrison unit to a watchtower when it's constructed.
The function implementing the Building Done handler should be declared as follows:
void __thiscall dwarf_hammer_tower_done_handler(SF_CGdBuildingToolbox *_this, uint16_t building_index)
{
}The full list of vanilla Building Done handlers can be checked here.
The Deal Damage Handler is called whenever a figure gets damaged, provided the attacked figure is currently under the effect of a spell which was linked to the Deal Damage handler during mod initialization.
The handler provides Figure Toolbox global object, source index, target index, amount of incoming damage, flag determining whether damage belongs to spell, flag determining whether damage is ranged and the index of the spell, if damage is dealt by a spell.
The function implementing the Deal Damage handler should be declared as follows:
uint16_t __thiscall custom_spell_deal_damage_handler(SF_CGdFigureToolbox *_toolbox, uint16_t source, uint16_t target, uint16_t current_damage, uint16_t is_spell_damage, uint32_t is_ranged_damage, uint16_t spell_id)
{
return current_damage; // this handler obligatory has to return some value, otherwise the damage calculation gets unpredictable
}The full list of vanilla Deal Damage handlers can be checked here.
This handler is called whenever a unit possessing the spell sees at least one target doesn't matter whether it's hostile or friendly.
The handler provides Battle Development global object which acts as collection of lists of all figures and buildings in unit's sight, grouped by their relationship to the initial unit (ally, hostile).
The handler provides the target index at which the spell will be aimed. Also, the spell provides the spell line (Spell Type ID) of a spell that will be cast.
The handler must return an integer value that determines the priority of the spell in question. The value 0 stands for not casting the spell, 1 stands for the highest priority, and after that the higher value stands for the lower priority.
The function implementing the Single Target AI handler should be declared as follows:
uint32_t __thiscall shield_wall_universal_ai_handler(SF_CGdBattleDevelopment *_this, uint16_t target_index, uint16_t spell_line, SF_CGdResourceSpell *spell_data)
{
return 1;
}The full list of vanilla Single Target AI handlers can be checked here.
The Spell Effect handler is used to link a spell of a given type to a function which runs the main logic for a spell.
The function implementing the Spell Effect handler should be declared as follows:
void __thiscall custom_spell_effect_handler(SF_CGdSpell *_this, uint16_t spell_index)
{
}The full list of vanilla Spell Effect handlers can be checked here.
The Spell End handler is automatically called by engine when the spell has to be stopped, but hasn't been terminated in the right manner as part of Spell Effect handler.
The function implementing the Spell End handler should be declared as follows:
void __thiscall custom_spell_end_handler(SF_CGdSpell *_this, uint16_t spell_index)
{
}The full list of vanilla Spell Eтв handlers can be checked here.
The On Hit handler is triggered whenever a creature makes a hit, provided the creature is currently under the effect of a spell linked to this handler.
Alternatively, this handler gets triggered when the creature affected was hit if the spell behavior was alternated with applying the spell tag TARGET_ONHIT_SPELL.
The Phase parameter will determine the exact phase of the damage calculation when this handler is triggered.
The function implementing the On Hit handler should be declared as follows:
uint16_t __thiscall custom_spell_onhit_handler(SF_CGdFigureJobs *_this, uint16_t source_index, uint16_t target_index, uint16_t damage)
{
return damage; // this handler obligatory has to return some value, otherwise the damage calculation gets unpredictable
}The full list of vanilla On Hit handlers can be checked here.
The Spell Refresh handler is used to determine whether the target has already been affected by a previous instance of the same spell or by another spell that provides a similar effect that interferes with the effect we are going to apply to the affected target.
This handler is triggered with a wrapper function spellAPI->checkCanApply(*SF_CGdSpell, spell_index)(see here) which is typically called within a Spell Effect handler during the initial tick.
The function implementing the Spell Refresh handler should be declared as follows:
int __thiscall custom_spell_refresh_handler(SF_CGdSpell *_this, uint16_t spell_index)
{
return 1;
}The full list of vanilla Spell Refresh handlers can be checked here.
The Spell Subeffect handler is used to nest an additional logic within the main logic of a spell.
The function implementing the Spell Subeffect handler should be declared as follows:
void __thiscall custom_spell_sub_effect_handler(SF_CGDEffect *_this, uint16_t effect_index)
{
}The full list of vanilla Spell Subeffect handlers can be checked here.
The Spell Type handler is used to assign a spell its job, which defines the spell core logic. Additionally, the Spell Type handler can be used to initialize starting parameters of the spell such as current tick and so on.
The function implementing the Spell Type handler should be declared as follows:
void __thiscall custom_spell_handler(SF_CGdSpell *_this, uint16_t spell_index)
{
_this->active_spell_list[spell_index].spell_job = CUSTOM_JOB;
}The full list of vanilla Spell Type handlers can be checked here.
A spell tag can be used to alternate the default behavior of spell according to one of templates, those are listed below:
NONE = 0,
SUMMON_SPELL,
DOMINATION_SPELL,
CHAIN_SPELL,
WHITE_AURA_SPELL, // In Future versions, we may be able to refactor AURA tags to be more dynamic
BLACK_AURA_SPELL,
TARGET_ONHIT_SPELL,
SPELL_TAG_COUNT