Zillameth on 12/3/2005 at 13:33
This is a step-by-step description of my attempt to create a fire elemental. While I believe this attempt was succesful, the process requires further improvements. Any advice would be highly appreciated.
1. Data structure
While creating a new class is not obligatory, it saves lots of time in the long run. I created my FireElemental as a child class of T3AIPawnCreatureUndead, because I thought I could use some of undead default settings. Now I think this was a poor choice, because I had to change everything anyway.
2. Properties
The following changes have been applied to the newly created class:
Actor->VoiceTag: set to null string
Zombie voice (+Voice_zombie_m) seemed appropriate at first, but then turned out to be too "zombish". The best solution would be to create a new schema for the elemental, but I don't know how to do that, so instead I decided to set up sounds with scripts (see below).
AI->AnimationSpeedMultiplayer: 0.65
Fire Elemental is powerful, particularly because it has its own source of light, doesn't seem to get tired and can be effectively fought only with water arrows. It needs to be slowed down, so that player can at least escape.
AIPawn->CombatModelClass: ZombieCombatModel
AIPawn->MovementModelClass: ThinMovementModel
I chose these settings, because zombie is a mindless, agressive monster, and I wanted fire elementals to behave like mindless, agressive monsters. I chose a human movement model for aesthetic reasons.
Render->SkeletalTag: GuardSkinny
Render->MaterialSkin: Zombie_01
Material skin is not very important, because it will be invisible.
Render->CastShadows: ShadowCastingFalse
Render->Transparency: 1.0
That's right, fire elemental is invisible. Or maybe I should say: its mesh is invisible. We only need its animations and skeleton.
Sound->CharacterType: set to null string
Sound->SoundAmbient->fireplace_lp
These two properties cause elemental to not make any footstep sounds. Instead, a quiet sound of fire will be heard in elemental's close proximity. Unfortunately, this sound is, in my opinion, too quiet (more precisely, its range is too short). As yet I don't know how to fix it.
3. Body
The trick is very simple: I made elemental's mesh invisible, but attached several flame emitters to it. I used RigidAttachment links, so flames follow elemental's animations. I find the effect quite convincing. The kind and placement of flames is a matter of taste and my choice is probably not the best. I linked FROM FireElemental TO TorchFlame with Attachment->m_parent_Bone set to:
HP_RightHand
HP_LeftHand
HP_RightHip
HP_LeftHip
HP_RightKnee
HP_LeftKnee
M1 L Toe0
M1 R Toe0
I also linked FROM FireElemental TO FireplaceFlame with Attachment->m_parent_Bone set to:
HP_Head
HP_FrontWaist
Each link has a property Link->m_name. I set all of them to Flames. This is a custom name, it doesn't need to be exactly that. It will be needed for scripts.
Note 1: these are links between archetypes. Concretes are created on mission start.
Note 2: if attachments to leg bones are ommited, fire elemental will appear to be floating a few feet above ground, just like in Dark Project. It will not have ability to fly, though.
Note 3: It is, theoretically, possible to use custom emitters (and sounds) to create air elementals, water elementals, gas elementals, electricity elementals or even pudding elementals.
Note 4: The more emitters are used, the more data engine has to process, so it's best to use as few of them, as possible.
4. Weaponry
At this point, Fire Elemental didn't have a weapon yet. In fact, leaving this data unset causes game to crash. I created a subclass of WorldObj->Setdressing->AIParts->AIFakeMeleeWeapon and called it AIInaudibleFakeMeleeWeapon. I made only one change to it: I set PhysicsSoung->PhysSoundTag to null string.
If you right click any Pawn class, there is an option called "Edit weapon loadout". It opens a window with a list of pawn's slots. I clicked LeftHip, then "Make Local", and then "Add Item to Slot". Then I chose AIInaudibleFakeMeleeWeapon. This gives the elemental ability to strike with its "hands".
5. Behaviour
Fire elemental may be as mindless as a zombie, but it differs from it in that it has different vulnerabilities. For example, water arrows hurt it and fire arrows don't. It also shouldn't slip on oil puddles. I set a Vulnerability link: FROM FireElemental TO FireVulnerability. Now we need to do something with these puddles. This requires alteration of a behaviour model class. I chose MetaProperty -> AIModel -> AIBehaviorModel -> T3BehaviorModel -> T3HumanBehaviorModel -> UndeadBehaviorModel -> ZombieBehaviorModel and created a subclass of it, called FireElementalBehaviorModel. I changed its AIStateFlags->StateEnabled_Slipping to 0.
6. Light Source
This part is a bit tricky. For some reason (and I have a feeling it's not a bug) it is impossible to spawn moveable lights in the same fashion emitters can be spawned. A concrete of such a light must be placed on map and then linked. I tried to add Lighting properties to elemental itself, but it didn't work properly, because during simulation light turned on and off for no apparent reason (and this is probably a bug, because when I add Lighting properties to Garrett, they work just fine).
My workaround for this problem is dirty, but effective. I lost my patience at this point, so I just created a hand torch, severed both its links, deleted both formerly linked emitters, turned off shadow casting, and set Render->Transparency to 0. Then I made a RigidAttachment link FROM fire elemental concrete TO my invisible torch with Attachment->m_parentBone set to HP_RightHand and ink->m_name set to Light Sources (this name is not precise, because I only use one source).
7. Scripting
I made four additional scripts. They mostly handle FX. Some of them wouldn't be necessary if I hadn't set all those sound tags to null strings. Certainly this part can be improved.
FireElementalAlerted
At first I wanted my elemental to bark only when it became alerted, but then it turned out that a more "talkative" monster seems more "interactive".
Conditions:
When my behavior state changes to [ANY].
//This might be way too often, but I didn't have time to experiment.
Actions:
Play sound schema [fire_short_burst] at my location.
//This is our "bark".
Reset script conditions and actions.
FireElementalAngry
When my fire elemental enters combat, it does what many animals do - it tries to be as scary as possible. It becomes louder and gives more light.
Conditions:
When linked AI [MYSELF] enters combat.
Actions:
Play sound schema [furnaceflameburst] at my location.
Play sound shcema [furnace_lp] at my location.
Set [LightShape.LightRadius] to [64] on linked objects of [RigidAttachment:Light Sources], changing it over time of [1.0] seconds.
//This looks much better than changing light range or brightness instantly.
Reset script conditions and actions.
FireElementalEndCombat
This is the opposite of the previous script. When elemental calms down, it, well, calms down.
Conditions:
When linked AI [MYSELF] exits combat
Query if [HealthState] is [Equal To] [HealthState_Alive] on any linked object(s) [MYSELF]
//When elemental dies, it exits combat too, but that's a special case and needs to be handled separately.
Actions:
Stop playing [furnaceflame_lp] at my location.
Play sound schema [furnaceflame_ext] at my location.
Set [LightShape.LightRadius] to [32] on linked objects of [RigidAttachment:Light Sources], changing it over time of [5.0] seconds.
Reset script conditions and actions.
FireElementalKilled
After death, elemental is totally invisible, so we might as well get rid of the body, so that it doesn't become an obstacle to player and other AIs.
Conditions:
When my [HealthState] changes to [HealthState_Dead] from [ANY]
Actions:
Set [LightShape.LightRadius] to [0] on linked objects of [RigidAttachment:Light Sources], changing it over time of [2.0] seconds.
//Just fading the light out didn't seem to work.
Finish playing [fireplace_lp] quickly (don't finich current loop) on my object.
Finish playing [furnaceflame_lp] quickly (don't finich current loop) on my object.
Play sound schema [furnaceflame_ext] at my location.
Delay [1.0] GAME seconds.
//We don't want flames to disappear immediately.
Set [EmitterSpawnState] to [EDS_NoNewParticles] on linked objects of [RigidAttachment:Flames]
Delay [2.0] GAME seconds.
// We need to give the object some time to finish playing the extinguish sound.
Destroy linked objects [RigidAttachment]
Destroy linked objects [MYSELF]
//Cleaning up.
8. Known issues.
I think there should be an additional sound when elemental is hit with water arrow. Just a matter of writing another short script, I guess.
Some sounds seem too quiet and others - too loud.
Light source has to be set up manually.
It looks like death animation is not played properly.
Sometimes I find an additional set of elemental's emitters on my map with no elemental attached to it.
When I close the editor, it now crashes while exporting scripts. I don't know the reason for that, and I'm worried, but everything gets saved and works fine when I launch the editor again.
When I kill an elemental, something that looks like a burnt out plank is spawned. Weird.
And there is over 90% probability I forgot about something while writing this message.
scumble on 12/3/2005 at 14:03
Fancy putting that in the wiki? It won't bite you ;)
Zillameth on 12/3/2005 at 14:10
I will do that, eventually, but I would like to wait a few days for comments and corrections.
Springheel on 12/3/2005 at 15:25
Any chance of a screenshot? :)
Karkianman on 12/3/2005 at 16:01
i thought fire elementals were just floating orbs of fire that shot fire arrows?
Zillameth on 12/3/2005 at 16:19
Quote Posted by Karkianman
i thought fire elementals were just floating orbs of fire that shot fire arrows?
They were, indeed, floating orbs of fire, although their projectiles were definitely not arrows. Maybe I'll try to recreate them in this canonic form, when I have time. For now, I would like to concentrate on the mission I'm currently working on and for that mission I need a walking creature. :)
Rantako on 12/3/2005 at 17:33
BRILLIANT!
Great work, Zillameth. I don't know how people come up with these things :thumb:
Some suggestions for improvement:
Instead of creating a concrete hand torch and linking from the fire elemental, create a new Actor Class under hand torch with the property Render->Transparency:1.0, then create a Rigid Attachment link from the Elemental archetype to your new invisible torch archetype and set up the parent bone thing as normal. This means that any new FireElementals you create will already have the torch.
I find that putting another action in the FireElementalAngry script, 'Play sound schema [hit arrowfire lo] at my location' gives a good effect - its the quieter fire arrow sound, makes it sound like the elemental is 'roaring' in rage.
As I said, this thing's great - I've already thought of a use for it in my FM
Zillameth on 12/3/2005 at 18:12
Quote Posted by Rantako
Some suggestions for improvement:
Instead of creating a concrete hand torch and linking from the fire elemental, create a new Actor Class under hand torch with the property Render->Transparency:1.0, then create a Rigid Attachment link from the Elemental archetype to your new invisible torch archetype and set up the parent bone thing as normal. This means that any new FireElementals you create will already have the torch.
I must admit, it works. I'm saying "admit", because I have already tried exactly the above once, and it didn't work. Which means I must have messed something up.
Quote Posted by Rantako
I find that putting another action in the FireElementalAngry script, 'Play sound schema [hit arrowfire lo] at my location' gives a good effect - its the quieter fire arrow sound, makes it sound like the elemental is 'roaring' in rage.
You're right, it sounds much better now. Meanwhile, I've been having some fun with schemas and it turned out that sound ranges can be adjusted very easily. As it is already known, schemas are text files and can be modified in any text editor. There is an entry called "radii" with two parameters. I guess first parameter determines maximum radius, at which sound is played with maximum volume, and the second determines total range of sound. All, that needs to be done, is create copy of schema with different name and modified radii. Fireplace_lp is so quiet, because it has radii 1,25, while fire_short_burst has 1,150. When I made modified versions, both with radii 10,50, sound volumes became more balanced.
jolynsbass on 12/3/2005 at 23:36
Quote Posted by Karkianman
i thought fire elementals were just floating orbs of fire that shot fire arrows?
There was also a "Fire elemental" of sorts, shaped like a man, in the Thief Gold mission where you are trying to get to the cathedral for the first time(I forget the name of that mission just now...) I'm not sure, but I think these kind of elementals are only in TG, and not in TDP(nor TMA)... I remember being very scared of said elemental... Your screenshot looks great - scary and vague like the original. :thumb: