https://wiki.thedarkmod.com/api.php?action=feedcontributions&user=Angua&feedformat=atomThe DarkMod Wiki - User contributions [en]2024-03-29T09:34:40ZUser contributionsMediaWiki 1.39.5https://wiki.thedarkmod.com/index.php?title=Missing_assets_for_standalone_TDM&diff=15806Missing assets for standalone TDM2012-12-14T11:02:30Z<p>Angua: /* Sounds */</p>
<hr />
<div><!-- search keywords: standalone free doom3 doom stand-alone--><br />
This page contains a list of assets that need to be replaced to make The Dark Mod stand-alone, that is to be able to play missions without having Doom 3 installed.<br />
<br />
{{infobox|bg=#e06060|fg=#ffff30|This list is incomplete!}}<br />
<br />
<br />
== Missing assets ==<br />
<br />
=== Textures ===<br />
<br />
The material shaders have now all been added, so we just miss the textures:<br />
<br />
Missing for the new SL (these might be shaders, not textures, it is hard to tell):<br />
<br />
* textures/decals/a_stain01_d01a<br />
* textures/decals/ballburn01_fx<br />
* textures/decals/dirtblast<br />
* textures/decals/dsplat5<br />
* textures/decals/fgrill2<br />
* textures/decals/genericdamage<br />
* textures/decals/graffiti2<br />
* textures/decals/handprint02<br />
* textures/decals/mcu_slimestain<br />
* textures/decals/scorch2<br />
* textures/decals/sdirt10<br />
* textures/decals/sdirt11<br />
* textures/decals/splat11<br />
* textures/decals/stain01b<br />
* textures/decals/stain02<br />
* textures/glass/glass1<br />
* textures/glass/outdoor_glass1fx<br />
* textures/hell/dirt02<br />
* textures/hell/dirt02_s<br />
* textures/particles/bloodspray<br />
* textures/particles/boomboom<br />
* textures/particles/droppuddle<br />
* textures/particles/fbeam<br />
* textures/particles/pfirebig<br />
* textures/particles/pfiresmall2<br />
* textures/particles/preamble<br />
* textures/particles/snowball<br />
<br />
Missing otherwise:<br />
<br />
* textures/decals/ballburn01<br />
* textures/decals/bloodspray<br />
* textures/decals/bulleth02<br />
* textures/decals/fly<br />
* textures/decals/hurt02<br />
* textures/decals/sdirt11a<br />
* textures/decals/splat1 .. textures/decals/splat9<br />
* textures/decals/stain01b<br />
* textures/decals/stain03<br />
* textures/decals/stainwall<br />
* textures/decals/stainwallfade<br />
* textures/glass/glass1<br />
* textures/glass/outdoor_glass1fx<br />
* textures/hell/dirt02<br />
* textures/hell/dirt02_s<br />
* textures/hell/wood1<br />
* textures/hell/lava1<br />
* textures/particles/billow3_glow<br />
* textures/particles/billow_glow<br />
* textures/particles/boomboom<br />
* textures/particles/boomboom2<br />
* textures/particles/boomboom3<br />
* textures/particles/drop2<br />
* textures/particles/droppuddle<br />
* textures/particles/dust<br />
* textures/particles/fbeam<br />
* textures/particles/pfiresmall2<br />
* textures/particles/plasma<br />
* textures/particles/preamble<br />
* textures/particles/snowball<br />
* textures/particles/spark3<br />
* textures/particles/s_lightning2_whi<br />
* textures/particles/s_lightning_masked<br />
* textures/sfx/vp1<br />
* textures/sfx/vpring3<br />
* thunderlight1<br />
* thunderlight2<br />
* thunderlightsky1<br />
* thunderlightsky2<br />
* topc<br />
<br />
=== Cube maps ===<br />
<br />
* env/gen2<br />
<br />
=== Sounds ===<br />
<br />
* _default.wav<br />
* activate_airpump_02.wav<br />
* admin_impdoor_creak.wav<br />
* alarm.wav<br />
* ambient_metal_stresses.wav<br />
* bodyparts.wav<br />
* bones_fall.wav<br />
* book_impact.wav<br />
* breakable_light_hum.wav<br />
* bridge_up_speaker.wav<br />
* bullet_impact_flesh.wav<br />
* bullet_impact_stone.wav<br />
* bullet_impact_wood.wav<br />
* <strike>burger_impact.wav</strike><br />
* caco_projectile.wav<br />
* cage_elevatordoor_close.wav<br />
* cage_elevatordoor_open.wav<br />
* ceiling_tiles.wav<br />
* cpu_m3_loop.wav<br />
* d3dm5_generator_off.wav<br />
* d3dm5_generator_on.wav<br />
* default_door_unlocked.wav (this is only used as temprorary sound for our entityDef atdm:alarm_sound entity... probably doesn't need a similar replacement)<br />
* e3_metalbash_01.wav<br />
* elevator_moving_loop.wav<br />
* fire_torch01_small.wav<br />
* fist_impact.wav<br />
* glass_bullethole.wav<br />
* glass_shatter.wav<br />
* hell_gatelower.wav<br />
* hh_door_movement_1.wav<br />
* light_flicker_104.wav<br />
* light_flicker_124.wav<br />
* light_hum_102.wav<br />
* loop_hum_01.wav<br />
* m3_loop.wav<br />
* m3_start.wav<br />
* m3_stop.wav<br />
* metalbounce_1.wav<br />
* monster_demon_archvile_die.wav<br />
* monster_demon_archvile_pain.wav<br />
* monster_demon_imp_fireball_explode.wav<br />
* monster_demon_imp_fireball_flight.wav<br />
* monster_demon_imp_melee_hit.wav<br />
* monster_demon_imp_melee_miss.wav<br />
* monster_demon_imp_thud.wav<br />
* monster_demon_maggot_melee2.wav<br />
* monster_demon_pinky_sight2.wav<br />
* monster_demon_tick_footstep.wav<br />
* monster_demon_trite_chatter.wav<br />
* monster_demon_trite_chatter_combat.wav<br />
* monster_demon_trite_death.wav<br />
* monster_demon_trite_melee.wav<br />
* monster_demon_trite_pain.wav<br />
* monster_demon_trite_sight.wav<br />
* <strike>monster_zombie_boney_chatter.wav</strike><br />
* <strike>monster_zombie_boney_chatter_combat.wav</strike><br />
* <strike>monster_zombie_boney_die.wav</strike><br />
* <strike>monster_zombie_boney_pain.wav</strike><br />
* <strike>monster_zombie_boney_sight.wav</strike><br />
* monster_zombie_maint_footstep.wav<br />
* monster_zombie_maint_thud.wav<br />
* null.wav<br />
* paper_impact.wav<br />
* pool_ball_impact.wav<br />
* rec1_steamchuff.wav<br />
* sound/ambient/loop_rumble_01.wav<br />
* <strike>sound/doors/hell/open_02.wav</strike><br />
* sound/doors/large/hugedoor_01_open.wav<br />
* sound/ed/admin/light_break.wav<br />
* sound/ed/archvile/breath1.wav .. sound/ed/archvile/breath3.wav<br />
* sound/ed/cherub/evillaugh2.ogg<br />
* sound/ed/cyberdemon/chatter1.wav .. sound/ed/cyberdemon/chatter4.wav<br />
* sound/ed/elevator/elev_end.wav<br />
* sound/ed/elevator/elev_start.wav<br />
* sound/ed/imp/alert_test32.wav<br />
* sound/ed/imp/alert_test33.wav<br />
* sound/ed/imp/alert_test34.wav<br />
* sound/ed/imp/alert_test39.wav<br />
* sound/ed/maggot/hiss3h2.ogg<br />
* sound/ed/pinky/pain_test1.wav .. sound/ed/pinky/pain_test7.wav<br />
* sound/ed/pinky3/death_test1.wav .. sound/ed/pinky3/death_test5.wav<br />
* sound/ed/pinky3/idle_test1.wav .. sound/ed/pinky3/idle_test4.wav<br />
* sound/ed/pinky3/sight3_test1.wav .. sound/ed/pinky3/sight3_test4.wav<br />
* sound/ed/pinky3/sight_test21.wav<br />
* sound/ed/pinky3/sight_test22.wav<br />
* sound/ed/pinky3/sight_test23.wav<br />
* sound/ed/player/player_land2.ogg<br />
* sound/ed/spook/ohgodplease.ogg<br />
* sound/ed/spook/please.ogg<br />
* sound/ed/tick/chirp1.ogg .. sound/ed/tick/chirp6.ogg<br />
* sound/ed/tick/tick_death1.ogg .. sound/ed/tick/tick_death3.ogg<br />
* sound/ed/tick/tick_pain1.ogg .. sound/ed/tick/tick_pain4.ogg<br />
* <strike>sound/ed/tick/tick_walk1.wav .. sound/ed/tick/tick_walk6.wav</strike><br />
* sound/ed/trite/breath_hollow_deep4.ogg<br />
* sound/ed/trite/breath_hollow_raspy1.ogg<br />
* sound/ed/trite/breath_throaty6.ogg<br />
* sound/impact/ambient_impacts/emetal_01.wav .. sound/impact/ambient_impacts/emetal_05.wav<br />
* sound/impact/boxes/boxfall_18.ogg<br />
* sound/impact/crash/glasscrash_01.ogg .. sound/impact/crash/glasscrash_04.ogg<br />
* sound/impact/metal_doors/slam_01.ogg<br />
* sound/impact/metal_doors/slam_08_boomy.wav<br />
* sound/impact/metals/1shot_metalhit_01.ogg<br />
* sound/impact/metals/1shot_metalhit_03.ogg<br />
* sound/impact/metals/1shot_metalhit_06.ogg<br />
* sound/impact/shaky_metal_bangs/mbang_01.wav .. sound/impact/shaky_metal_bangs/mbang_05.wav<br />
* sound/impact/solid/impact_01.ogg<br />
* sound/impact/solid/impact_02.ogg<br />
* sound/impact/solid/impact_03.ogg<br />
* sound/impact/steel/clang_01.ogg<br />
* sound/impact/steel/clang_02.ogg<br />
* sound/impact/steel/clang_03.ogg<br />
* sound/impact/steel/clang_04.wav<br />
* sound/impact/steel/clang_05.ogg<br />
* sound/levels/caverns2/stone_movement_loop.wav<br />
* sound/levels/hell/thunderclap_01a.wav<br />
* sound/levels/hell/thunderclap_02a.wav<br />
* sound/levels/hell/thunderclap_03a.wav<br />
* sound/levels/hell/thunderclap_04a.wav<br />
* sound/machinery/loop_machinery_03.wav<br />
* sound/machinery/machines/loop_airpump_02.wav<br />
* sound/machinery/machines/loop_machinery_01.ogg<br />
* sound/machinery/machines/loop_machinery_02.ogg<br />
* sound/machinery/steamchuffs/steamchuff_01.ogg<br />
* sound/machinery/steamchuffs/steamchuff_02.ogg<br />
* sound/monsters/cacodemon/caco_chatter1.wav .. sound/monsters/cacodemon/caco_chatter6.wav<br />
* sound/monsters/cacodemon/pimpact_01.wav .. sound/monsters/cacodemon/pimpact_04.wav<br />
* sound/monsters/lost_soul/chatter_01.wav .. sound/monsters/lost_soul/chatter_03.wav<br />
* sound/monsters/maggot/distant_screams_01.ogg<br />
* sound/monsters/maggot/distant_screams_03.ogg<br />
* sound/monsters/maggot/idle_01.wav<br />
* sound/monsters/maggot/idle_02.wav<br />
* sound/monsters/maggot/idle_03.wav<br />
* sound/monsters/maggot/idle_04.wav<br />
* sound/monsters/trite/death21.wav<br />
* sound/monsters/trite/death22.wav<br />
* sound/monsters/trite/death23.wav<br />
* sound/monsters/trite/pain8.wav<br />
* sound/monsters/trite/pain9.wav<br />
* sound/monsters/trite/sight1.wav<br />
* sound/monsters/trite/sight3.wav<br />
* sound/monsters/trite/sight5.wav<br />
* sound/movers/_general_movement/m3_end.wav<br />
* sound/movers/_general_movement/m3_loop.wav<br />
* sound/movers/_general_movement/m3_start.wav<br />
* sound/sfx/voices/generic/brush01.ogg<br />
* sound/stress/1shot_creaking_02.wav<br />
* sound/weapons/explosions/explode_01.wav<br />
* sound/weapons/explosions/impexp_03.wav<br />
* sound/weapons/explosions/impexp_04.wav<br />
* sound/weapons/explosions/impexp_05.wav<br />
* sound/weapons/explosions/impexp_06.wav<br />
* sound/xian/creepy/prayer/deliver_us.ogg<br />
* sound/xian/foley_sessions/coughs/cough_01.ogg .. sound/xian/foley_sessions/coughs/cough_05.ogg<br />
* sound/xian/roomtones2/dangerlow_01.wav<br />
* sound/xian/suspense/loop_suspense_07.wav<br />
* steam_01.wav<br />
* steelswing_01.wav<br />
* stone_movement_end.wav<br />
* teleport_machine_idle.wav<br />
* tincan.wav<br />
* vault_clock_ambient.wav<br />
* wind_01.wav<br />
* wind_02.wav<br />
<br />
angua: these were used in the sound shader small_metal_impact, replaced with similar tdm sounds:<br />
* <strike>sound/weapons/casings/small_metal_02.wav</strike><br />
* <strike>sound/weapons/impacts/bullet_metal/metalimpact_04.wav</strike><br />
* <strike>sound/xian/foley_sessions/metals_small/lowtink_01.ogg .. sound/xian/foley_sessions/metals_small/lowtink_03.ogg</strike><br />
* <strike>sound/impact/stairs/simpact_04.ogg</strike><br />
<br />
angua: these were used in the sound shader med_metal_impact, replaced with similar tdm sounds:<br />
* <strike>sound/ed/sfx/barrel1.ogg .. sound/ed/sfx/barrel5.ogg</strike><br />
* <strike>sound/ed/sfx/wrench_impact1.ogg</strike><br />
* <strike>sound/ed/sfx/wrench_impact2.ogg</strike><br />
<br />
==== Unused, but generating warnings ====<br />
<br />
These are probably automatically loaded, but never used and can be removed in the code:<br />
<br />
* player_sounds_doublevision.wav<br />
* player_sounds_guienter.wav<br />
* player_sounds_guiexit.wav<br />
* player_sounds_heartbeat.wav<br />
* player_sounds_heartbeat_dying.wav<br />
* player_sounds_hitflesh.wav<br />
* player_sounds_skipcinematic.wav<br />
* player_sounds_teleportexit.wav<br />
* player_sounds_teleportstart.wav<br />
* player_sounds_thud.wav<br />
<br />
=== AI ===<br />
<br />
* Zombie + animations<br />
* Joint 'Shoulders' not found for 'head_joint' on 'atdm_ai_undead_zombie_a...<br />
* models/md5/monsters/skeleton/skeleton.md5mesh<br />
<br />
=== Animations ===<br />
<br />
* models/md5/characters/npcs/zheads/z1idle.md5anim<br />
* models/md5/chars/af_pose.md5anim<br />
* models/md5/environments/hellchain.md5anim<br />
* models/md5/environments/swinglight_round.md5anim<br />
* models/md5/monsters/imp/initial.md5anim<br />
<br />
=== AF (Articulated Figures) ===<br />
<br />
* monster_demon_imp<br />
* monster_zombie_base<br />
* monster_zombie_bernie<br />
<br />
=== Models ===<br />
<br />
Static and moveable models, not counting meshes (for AI). These are missing and need to be redone:<br />
<br />
* models/gibs/brain_2xb.lwo<br />
* models/gibs/gib_left_arm.lwo<br />
* models/gibs/gib_left_leg.lwo<br />
* models/gibs/gib_right_foot.lwo<br />
* models/gibs/gib_torso.lwo<br />
* models/gibs/left_waist_pork.lwo<br />
* models/gibs/lup_leg_pork.lwo<br />
* models/mapobjects/caves/caverock1.ase<br />
* models/mapobjects/hell/mancroom/bars.lwo<br />
* models/mapobjects/lights/cagelight/cagelight.lwo<br />
* models/mapobjects/tables/bunkbed/mattress.lwo<br />
<br />
This one is a place holder for a quiver model, so we need a quiver instead this:<br />
<br />
* models/items/shells_ammo/shells_large.lwo<br />
<br />
We do miss some models altogether, and some models are modified versions of D3 meshes.<br />
They won't throw an error because they're included in the mod, but they can't be left in if TDM is going standalone:<br />
<br />
* pick-axe<br />
* wooden tray<br />
* several chain models<br />
* skull01 model<br />
* candle textures (and possibly mesh)<br />
* jar<br />
* noblewoman's legs<br />
* beggar's arms and legs<br />
* werebeast body<br />
* Sykes head and textures<br />
* head08 mesh and textures<br />
* head06 mesh and textures<br />
* head01 mesh and textures<br />
<br />
== See also ==<br />
<br />
* [[IdTech4 Open Source]]<br />
* [[Standalone Progress]]<br />
<br />
{{standalone}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Missing_assets_for_standalone_TDM&diff=15789Missing assets for standalone TDM2012-11-09T17:37:02Z<p>Angua: /* Sounds */</p>
<hr />
<div><!-- search keywords: standalone free doom3 doom stand-alone--><br />
This page contains a list of assets that need to be replaced to make The Dark Mod stand-alone, that is to be able to play missions without having Doom 3 installed.<br />
<br />
{{infobox|bg=#e06060|fg=#ffff30|This list is incomplete!}}<br />
<br />
<br />
== Missing assets ==<br />
<br />
=== Textures ===<br />
<br />
The material shaders have now all been added, so we just miss the textures:<br />
<br />
Missing for the new SL (these might be shaders, not textures, it is hard to tell):<br />
<br />
* textures/decals/a_stain01_d01a<br />
* textures/decals/ballburn01_fx<br />
* textures/decals/dirtblast<br />
* textures/decals/dsplat5<br />
* textures/decals/fgrill2<br />
* textures/decals/genericdamage<br />
* textures/decals/graffiti2<br />
* textures/decals/handprint02<br />
* textures/decals/mcu_slimestain<br />
* textures/decals/scorch2<br />
* textures/decals/sdirt10<br />
* textures/decals/sdirt11<br />
* textures/decals/splat11<br />
* textures/decals/stain01b<br />
* textures/decals/stain02<br />
* textures/glass/glass1<br />
* textures/glass/outdoor_glass1fx<br />
* textures/hell/dirt02<br />
* textures/hell/dirt02_s<br />
* textures/particles/bloodspray<br />
* textures/particles/boomboom<br />
* textures/particles/droppuddle<br />
* textures/particles/fbeam<br />
* textures/particles/pfirebig<br />
* textures/particles/pfiresmall2<br />
* textures/particles/preamble<br />
* textures/particles/snowball<br />
<br />
Missing otherwise:<br />
<br />
* textures/decals/ballburn01<br />
* textures/decals/bloodspray<br />
* textures/decals/bulleth02<br />
* textures/decals/fly<br />
* textures/decals/hurt02<br />
* textures/decals/sdirt11a<br />
* textures/decals/splat1 .. textures/decals/splat9<br />
* textures/decals/stain01b<br />
* textures/decals/stain03<br />
* textures/decals/stainwall<br />
* textures/decals/stainwallfade<br />
* textures/glass/glass1<br />
* textures/glass/outdoor_glass1fx<br />
* textures/hell/dirt02<br />
* textures/hell/dirt02_s<br />
* textures/hell/wood1<br />
* textures/hell/lava1<br />
* textures/particles/billow3_glow<br />
* textures/particles/billow_glow<br />
* textures/particles/boomboom<br />
* textures/particles/boomboom2<br />
* textures/particles/boomboom3<br />
* textures/particles/drop2<br />
* textures/particles/droppuddle<br />
* textures/particles/dust<br />
* textures/particles/fbeam<br />
* textures/particles/pfiresmall2<br />
* textures/particles/plasma<br />
* textures/particles/preamble<br />
* textures/particles/snowball<br />
* textures/particles/spark3<br />
* textures/particles/s_lightning2_whi<br />
* textures/particles/s_lightning_masked<br />
* textures/sfx/vp1<br />
* textures/sfx/vpring3<br />
* thunderlight1<br />
* thunderlight2<br />
* thunderlightsky1<br />
* thunderlightsky2<br />
* topc<br />
<br />
=== Cube maps ===<br />
<br />
* env/gen2<br />
<br />
=== Sounds ===<br />
<br />
* _default.wav<br />
* activate_airpump_02.wav<br />
* admin_impdoor_creak.wav<br />
* alarm.wav<br />
* ambient_metal_stresses.wav<br />
* bodyparts.wav<br />
* bones_fall.wav<br />
* book_impact.wav<br />
* breakable_light_hum.wav<br />
* bridge_up_speaker.wav<br />
* bullet_impact_flesh.wav<br />
* bullet_impact_stone.wav<br />
* bullet_impact_wood.wav<br />
* <strike>burger_impact.wav</strike><br />
* caco_projectile.wav<br />
* cage_elevatordoor_close.wav<br />
* cage_elevatordoor_open.wav<br />
* ceiling_tiles.wav<br />
* cpu_m3_loop.wav<br />
* d3dm5_generator_off.wav<br />
* d3dm5_generator_on.wav<br />
* default_door_unlocked.wav (this is only used as temprorary sound for our entityDef atdm:alarm_sound entity... probably doesn't need a similar replacement)<br />
* e3_metalbash_01.wav<br />
* elevator_moving_loop.wav<br />
* fire_torch01_small.wav<br />
* fist_impact.wav<br />
* glass_bullethole.wav<br />
* glass_shatter.wav<br />
* hell_gatelower.wav<br />
* hh_door_movement_1.wav<br />
* light_flicker_104.wav<br />
* light_flicker_124.wav<br />
* light_hum_102.wav<br />
* loop_hum_01.wav<br />
* m3_loop.wav<br />
* m3_start.wav<br />
* m3_stop.wav<br />
* metalbounce_1.wav<br />
* monster_demon_archvile_die.wav<br />
* monster_demon_archvile_pain.wav<br />
* monster_demon_imp_fireball_explode.wav<br />
* monster_demon_imp_fireball_flight.wav<br />
* monster_demon_imp_melee_hit.wav<br />
* monster_demon_imp_melee_miss.wav<br />
* monster_demon_imp_thud.wav<br />
* monster_demon_maggot_melee2.wav<br />
* monster_demon_pinky_sight2.wav<br />
* monster_demon_tick_footstep.wav<br />
* monster_demon_trite_chatter.wav<br />
* monster_demon_trite_chatter_combat.wav<br />
* monster_demon_trite_death.wav<br />
* monster_demon_trite_melee.wav<br />
* monster_demon_trite_pain.wav<br />
* monster_demon_trite_sight.wav<br />
* <strike>monster_zombie_boney_chatter.wav</strike><br />
* <strike>monster_zombie_boney_chatter_combat.wav</strike><br />
* <strike>monster_zombie_boney_die.wav</strike><br />
* <strike>monster_zombie_boney_pain.wav</strike><br />
* <strike>monster_zombie_boney_sight.wav</strike><br />
* monster_zombie_maint_footstep.wav<br />
* monster_zombie_maint_thud.wav<br />
* null.wav<br />
* paper_impact.wav<br />
* pool_ball_impact.wav<br />
* rec1_steamchuff.wav<br />
* sound/ambient/loop_rumble_01.wav<br />
* <strike>sound/doors/hell/open_02.wav</strike><br />
* sound/doors/large/hugedoor_01_open.wav<br />
* sound/ed/admin/light_break.wav<br />
* sound/ed/archvile/breath1.wav .. sound/ed/archvile/breath3.wav<br />
* sound/ed/cherub/evillaugh2.ogg<br />
* sound/ed/cyberdemon/chatter1.wav .. sound/ed/cyberdemon/chatter4.wav<br />
* sound/ed/elevator/elev_end.wav<br />
* sound/ed/elevator/elev_start.wav<br />
* sound/ed/imp/alert_test32.wav<br />
* sound/ed/imp/alert_test33.wav<br />
* sound/ed/imp/alert_test34.wav<br />
* sound/ed/imp/alert_test39.wav<br />
* sound/ed/maggot/hiss3h2.ogg<br />
* sound/ed/pinky/pain_test1.wav .. sound/ed/pinky/pain_test7.wav<br />
* sound/ed/pinky3/death_test1.wav .. sound/ed/pinky3/death_test5.wav<br />
* sound/ed/pinky3/idle_test1.wav .. sound/ed/pinky3/idle_test4.wav<br />
* sound/ed/pinky3/sight3_test1.wav .. sound/ed/pinky3/sight3_test4.wav<br />
* sound/ed/pinky3/sight_test21.wav<br />
* sound/ed/pinky3/sight_test22.wav<br />
* sound/ed/pinky3/sight_test23.wav<br />
* sound/ed/player/player_land2.ogg<br />
* sound/ed/sfx/barrel1.ogg .. sound/ed/sfx/barrel5.ogg<br />
* sound/ed/sfx/wrench_impact1.ogg<br />
* sound/ed/sfx/wrench_impact2.ogg<br />
* sound/ed/spook/ohgodplease.ogg<br />
* sound/ed/spook/please.ogg<br />
* sound/ed/tick/chirp1.ogg .. sound/ed/tick/chirp6.ogg<br />
* sound/ed/tick/tick_death1.ogg .. sound/ed/tick/tick_death3.ogg<br />
* sound/ed/tick/tick_pain1.ogg .. sound/ed/tick/tick_pain4.ogg<br />
* <strike>sound/ed/tick/tick_walk1.wav .. sound/ed/tick/tick_walk6.wav</strike><br />
* sound/ed/trite/breath_hollow_deep4.ogg<br />
* sound/ed/trite/breath_hollow_raspy1.ogg<br />
* sound/ed/trite/breath_throaty6.ogg<br />
* sound/impact/ambient_impacts/emetal_01.wav .. sound/impact/ambient_impacts/emetal_05.wav<br />
* sound/impact/boxes/boxfall_18.ogg<br />
* sound/impact/crash/glasscrash_01.ogg .. sound/impact/crash/glasscrash_04.ogg<br />
* sound/impact/metal_doors/slam_01.ogg<br />
* sound/impact/metal_doors/slam_08_boomy.wav<br />
* sound/impact/metals/1shot_metalhit_01.ogg<br />
* sound/impact/metals/1shot_metalhit_03.ogg<br />
* sound/impact/metals/1shot_metalhit_06.ogg<br />
* sound/impact/shaky_metal_bangs/mbang_01.wav .. sound/impact/shaky_metal_bangs/mbang_05.wav<br />
* sound/impact/solid/impact_01.ogg<br />
* sound/impact/solid/impact_02.ogg<br />
* sound/impact/solid/impact_03.ogg<br />
* sound/impact/stairs/simpact_04.ogg<br />
* sound/impact/steel/clang_01.ogg<br />
* sound/impact/steel/clang_02.ogg<br />
* sound/impact/steel/clang_03.ogg<br />
* sound/impact/steel/clang_04.wav<br />
* sound/impact/steel/clang_05.ogg<br />
* sound/levels/caverns2/stone_movement_loop.wav<br />
* sound/levels/hell/thunderclap_01a.wav<br />
* sound/levels/hell/thunderclap_02a.wav<br />
* sound/levels/hell/thunderclap_03a.wav<br />
* sound/levels/hell/thunderclap_04a.wav<br />
* sound/machinery/loop_machinery_03.wav<br />
* sound/machinery/machines/loop_airpump_02.wav<br />
* sound/machinery/machines/loop_machinery_01.ogg<br />
* sound/machinery/machines/loop_machinery_02.ogg<br />
* sound/machinery/steamchuffs/steamchuff_01.ogg<br />
* sound/machinery/steamchuffs/steamchuff_02.ogg<br />
* sound/monsters/cacodemon/caco_chatter1.wav .. sound/monsters/cacodemon/caco_chatter6.wav<br />
* sound/monsters/cacodemon/pimpact_01.wav .. sound/monsters/cacodemon/pimpact_04.wav<br />
* sound/monsters/lost_soul/chatter_01.wav .. sound/monsters/lost_soul/chatter_03.wav<br />
* sound/monsters/maggot/distant_screams_01.ogg<br />
* sound/monsters/maggot/distant_screams_03.ogg<br />
* sound/monsters/maggot/idle_01.wav<br />
* sound/monsters/maggot/idle_02.wav<br />
* sound/monsters/maggot/idle_03.wav<br />
* sound/monsters/maggot/idle_04.wav<br />
* sound/monsters/trite/death21.wav<br />
* sound/monsters/trite/death22.wav<br />
* sound/monsters/trite/death23.wav<br />
* sound/monsters/trite/pain8.wav<br />
* sound/monsters/trite/pain9.wav<br />
* sound/monsters/trite/sight1.wav<br />
* sound/monsters/trite/sight3.wav<br />
* sound/monsters/trite/sight5.wav<br />
* sound/movers/_general_movement/m3_end.wav<br />
* sound/movers/_general_movement/m3_loop.wav<br />
* sound/movers/_general_movement/m3_start.wav<br />
* sound/sfx/voices/generic/brush01.ogg<br />
* sound/stress/1shot_creaking_02.wav<br />
* sound/weapons/casings/small_metal_02.wav<br />
* sound/weapons/explosions/explode_01.wav<br />
* sound/weapons/explosions/impexp_03.wav<br />
* sound/weapons/explosions/impexp_04.wav<br />
* sound/weapons/explosions/impexp_05.wav<br />
* sound/weapons/explosions/impexp_06.wav<br />
* sound/weapons/impacts/bullet_metal/metalimpact_04.wav<br />
* sound/xian/creepy/prayer/deliver_us.ogg<br />
* sound/xian/foley_sessions/coughs/cough_01.ogg .. sound/xian/foley_sessions/coughs/cough_05.ogg<br />
* <strike>sound/xian/foley_sessions/metals_small/lowtink_01.ogg .. sound/xian/foley_sessions/metals_small/lowtink_03.ogg</strike><br />
* sound/xian/roomtones2/dangerlow_01.wav<br />
* sound/xian/suspense/loop_suspense_07.wav<br />
* steam_01.wav<br />
* steelswing_01.wav<br />
* stone_movement_end.wav<br />
* teleport_machine_idle.wav<br />
* tincan.wav<br />
* vault_clock_ambient.wav<br />
* wind_01.wav<br />
* wind_02.wav<br />
<br />
==== Unused, but generating warnings ====<br />
<br />
These are probably automatically loaded, but never used and can be removed in the code:<br />
<br />
* player_sounds_doublevision.wav<br />
* player_sounds_guienter.wav<br />
* player_sounds_guiexit.wav<br />
* player_sounds_heartbeat.wav<br />
* player_sounds_heartbeat_dying.wav<br />
* player_sounds_hitflesh.wav<br />
* player_sounds_skipcinematic.wav<br />
* player_sounds_teleportexit.wav<br />
* player_sounds_teleportstart.wav<br />
* player_sounds_thud.wav<br />
<br />
=== AI ===<br />
<br />
* Zombie + animations<br />
* Joint 'Shoulders' not found for 'head_joint' on 'atdm_ai_undead_zombie_a...<br />
* models/md5/monsters/skeleton/skeleton.md5mesh<br />
<br />
=== Animations ===<br />
<br />
* models/md5/characters/npcs/zheads/z1idle.md5anim<br />
* models/md5/chars/af_pose.md5anim<br />
* models/md5/environments/hellchain.md5anim<br />
* models/md5/environments/swinglight_round.md5anim<br />
* models/md5/monsters/imp/initial.md5anim<br />
<br />
=== AF (Articulated Figures) ===<br />
<br />
* monster_demon_imp<br />
* monster_zombie_base<br />
* monster_zombie_bernie<br />
<br />
=== Models ===<br />
<br />
Static and moveable models, not counting meshes (for AI). These are missing and need to be redone:<br />
<br />
* models/gibs/brain_2xb.lwo<br />
* models/gibs/gib_left_arm.lwo<br />
* models/gibs/gib_left_leg.lwo<br />
* models/gibs/gib_right_foot.lwo<br />
* models/gibs/gib_torso.lwo<br />
* models/gibs/left_waist_pork.lwo<br />
* models/gibs/lup_leg_pork.lwo<br />
* models/mapobjects/caves/caverock1.ase<br />
* models/mapobjects/hell/mancroom/bars.lwo<br />
* models/mapobjects/lights/cagelight/cagelight.lwo<br />
* models/mapobjects/tables/bunkbed/mattress.lwo<br />
<br />
This one is a place holder for a quiver model, so we need a quiver instead this:<br />
<br />
* models/items/shells_ammo/shells_large.lwo<br />
<br />
We do miss some models altogether, and some models are modified versions of D3 meshes.<br />
They won't throw an error because they're included in the mod, but they can't be left in if TDM is going standalone:<br />
<br />
* pick-axe<br />
* wooden tray<br />
* several chain models<br />
* skull01 model<br />
* candle textures (and possibly mesh)<br />
* jar<br />
* noblewoman's legs<br />
* beggar's arms and legs<br />
* werebeast body<br />
* Sykes head and textures<br />
* head08 mesh and textures<br />
* head06 mesh and textures<br />
* head01 mesh and textures<br />
<br />
== See also ==<br />
<br />
* [[IdTech4 Open Source]]<br />
* [[Standalone Progress]]<br />
<br />
{{standalone}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Missing_assets_for_standalone_TDM&diff=15788Missing assets for standalone TDM2012-11-09T17:30:16Z<p>Angua: /* Sounds */</p>
<hr />
<div><!-- search keywords: standalone free doom3 doom stand-alone--><br />
This page contains a list of assets that need to be replaced to make The Dark Mod stand-alone, that is to be able to play missions without having Doom 3 installed.<br />
<br />
{{infobox|bg=#e06060|fg=#ffff30|This list is incomplete!}}<br />
<br />
<br />
== Missing assets ==<br />
<br />
=== Textures ===<br />
<br />
The material shaders have now all been added, so we just miss the textures:<br />
<br />
Missing for the new SL (these might be shaders, not textures, it is hard to tell):<br />
<br />
* textures/decals/a_stain01_d01a<br />
* textures/decals/ballburn01_fx<br />
* textures/decals/dirtblast<br />
* textures/decals/dsplat5<br />
* textures/decals/fgrill2<br />
* textures/decals/genericdamage<br />
* textures/decals/graffiti2<br />
* textures/decals/handprint02<br />
* textures/decals/mcu_slimestain<br />
* textures/decals/scorch2<br />
* textures/decals/sdirt10<br />
* textures/decals/sdirt11<br />
* textures/decals/splat11<br />
* textures/decals/stain01b<br />
* textures/decals/stain02<br />
* textures/glass/glass1<br />
* textures/glass/outdoor_glass1fx<br />
* textures/hell/dirt02<br />
* textures/hell/dirt02_s<br />
* textures/particles/bloodspray<br />
* textures/particles/boomboom<br />
* textures/particles/droppuddle<br />
* textures/particles/fbeam<br />
* textures/particles/pfirebig<br />
* textures/particles/pfiresmall2<br />
* textures/particles/preamble<br />
* textures/particles/snowball<br />
<br />
Missing otherwise:<br />
<br />
* textures/decals/ballburn01<br />
* textures/decals/bloodspray<br />
* textures/decals/bulleth02<br />
* textures/decals/fly<br />
* textures/decals/hurt02<br />
* textures/decals/sdirt11a<br />
* textures/decals/splat1 .. textures/decals/splat9<br />
* textures/decals/stain01b<br />
* textures/decals/stain03<br />
* textures/decals/stainwall<br />
* textures/decals/stainwallfade<br />
* textures/glass/glass1<br />
* textures/glass/outdoor_glass1fx<br />
* textures/hell/dirt02<br />
* textures/hell/dirt02_s<br />
* textures/hell/wood1<br />
* textures/hell/lava1<br />
* textures/particles/billow3_glow<br />
* textures/particles/billow_glow<br />
* textures/particles/boomboom<br />
* textures/particles/boomboom2<br />
* textures/particles/boomboom3<br />
* textures/particles/drop2<br />
* textures/particles/droppuddle<br />
* textures/particles/dust<br />
* textures/particles/fbeam<br />
* textures/particles/pfiresmall2<br />
* textures/particles/plasma<br />
* textures/particles/preamble<br />
* textures/particles/snowball<br />
* textures/particles/spark3<br />
* textures/particles/s_lightning2_whi<br />
* textures/particles/s_lightning_masked<br />
* textures/sfx/vp1<br />
* textures/sfx/vpring3<br />
* thunderlight1<br />
* thunderlight2<br />
* thunderlightsky1<br />
* thunderlightsky2<br />
* topc<br />
<br />
=== Cube maps ===<br />
<br />
* env/gen2<br />
<br />
=== Sounds ===<br />
<br />
* _default.wav<br />
* activate_airpump_02.wav<br />
* admin_impdoor_creak.wav<br />
* alarm.wav<br />
* ambient_metal_stresses.wav<br />
* bodyparts.wav<br />
* bones_fall.wav<br />
* book_impact.wav<br />
* breakable_light_hum.wav<br />
* bridge_up_speaker.wav<br />
* bullet_impact_flesh.wav<br />
* bullet_impact_stone.wav<br />
* bullet_impact_wood.wav<br />
* <strike>burger_impact.wav</strike><br />
* caco_projectile.wav<br />
* cage_elevatordoor_close.wav<br />
* cage_elevatordoor_open.wav<br />
* ceiling_tiles.wav<br />
* cpu_m3_loop.wav<br />
* d3dm5_generator_off.wav<br />
* d3dm5_generator_on.wav<br />
* default_door_unlocked.wav (this is only used as temprorary sound for our entityDef atdm:alarm_sound entity... probably doesn't need a similar replacement)<br />
* e3_metalbash_01.wav<br />
* elevator_moving_loop.wav<br />
* fire_torch01_small.wav<br />
* fist_impact.wav<br />
* glass_bullethole.wav<br />
* glass_shatter.wav<br />
* hell_gatelower.wav<br />
* hh_door_movement_1.wav<br />
* light_flicker_104.wav<br />
* light_flicker_124.wav<br />
* light_hum_102.wav<br />
* loop_hum_01.wav<br />
* m3_loop.wav<br />
* m3_start.wav<br />
* m3_stop.wav<br />
* metalbounce_1.wav<br />
* monster_demon_archvile_die.wav<br />
* monster_demon_archvile_pain.wav<br />
* monster_demon_imp_fireball_explode.wav<br />
* monster_demon_imp_fireball_flight.wav<br />
* monster_demon_imp_melee_hit.wav<br />
* monster_demon_imp_melee_miss.wav<br />
* monster_demon_imp_thud.wav<br />
* monster_demon_maggot_melee2.wav<br />
* monster_demon_pinky_sight2.wav<br />
* monster_demon_tick_footstep.wav<br />
* monster_demon_trite_chatter.wav<br />
* monster_demon_trite_chatter_combat.wav<br />
* monster_demon_trite_death.wav<br />
* monster_demon_trite_melee.wav<br />
* monster_demon_trite_pain.wav<br />
* monster_demon_trite_sight.wav<br />
* <strike>monster_zombie_boney_chatter.wav</strike><br />
* <strike>monster_zombie_boney_chatter_combat.wav</strike><br />
* <strike>monster_zombie_boney_die.wav</strike><br />
* <strike>monster_zombie_boney_pain.wav</strike><br />
* monster_zombie_boney_sight.wav<br />
* monster_zombie_maint_footstep.wav<br />
* monster_zombie_maint_thud.wav<br />
* null.wav<br />
* paper_impact.wav<br />
* pool_ball_impact.wav<br />
* rec1_steamchuff.wav<br />
* sound/ambient/loop_rumble_01.wav<br />
* <strike>sound/doors/hell/open_02.wav</strike><br />
* sound/doors/large/hugedoor_01_open.wav<br />
* sound/ed/admin/light_break.wav<br />
* sound/ed/archvile/breath1.wav .. sound/ed/archvile/breath3.wav<br />
* sound/ed/cherub/evillaugh2.ogg<br />
* sound/ed/cyberdemon/chatter1.wav .. sound/ed/cyberdemon/chatter4.wav<br />
* sound/ed/elevator/elev_end.wav<br />
* sound/ed/elevator/elev_start.wav<br />
* sound/ed/imp/alert_test32.wav<br />
* sound/ed/imp/alert_test33.wav<br />
* sound/ed/imp/alert_test34.wav<br />
* sound/ed/imp/alert_test39.wav<br />
* sound/ed/maggot/hiss3h2.ogg<br />
* sound/ed/pinky/pain_test1.wav .. sound/ed/pinky/pain_test7.wav<br />
* sound/ed/pinky3/death_test1.wav .. sound/ed/pinky3/death_test5.wav<br />
* sound/ed/pinky3/idle_test1.wav .. sound/ed/pinky3/idle_test4.wav<br />
* sound/ed/pinky3/sight3_test1.wav .. sound/ed/pinky3/sight3_test4.wav<br />
* sound/ed/pinky3/sight_test21.wav<br />
* sound/ed/pinky3/sight_test22.wav<br />
* sound/ed/pinky3/sight_test23.wav<br />
* sound/ed/player/player_land2.ogg<br />
* sound/ed/sfx/barrel1.ogg .. sound/ed/sfx/barrel5.ogg<br />
* sound/ed/sfx/wrench_impact1.ogg<br />
* sound/ed/sfx/wrench_impact2.ogg<br />
* sound/ed/spook/ohgodplease.ogg<br />
* sound/ed/spook/please.ogg<br />
* sound/ed/tick/chirp1.ogg .. sound/ed/tick/chirp6.ogg<br />
* sound/ed/tick/tick_death1.ogg .. sound/ed/tick/tick_death3.ogg<br />
* sound/ed/tick/tick_pain1.ogg .. sound/ed/tick/tick_pain4.ogg<br />
* <strike>sound/ed/tick/tick_walk1.wav .. sound/ed/tick/tick_walk6.wav</strike><br />
* sound/ed/trite/breath_hollow_deep4.ogg<br />
* sound/ed/trite/breath_hollow_raspy1.ogg<br />
* sound/ed/trite/breath_throaty6.ogg<br />
* sound/impact/ambient_impacts/emetal_01.wav .. sound/impact/ambient_impacts/emetal_05.wav<br />
* sound/impact/boxes/boxfall_18.ogg<br />
* sound/impact/crash/glasscrash_01.ogg .. sound/impact/crash/glasscrash_04.ogg<br />
* sound/impact/metal_doors/slam_01.ogg<br />
* sound/impact/metal_doors/slam_08_boomy.wav<br />
* sound/impact/metals/1shot_metalhit_01.ogg<br />
* sound/impact/metals/1shot_metalhit_03.ogg<br />
* sound/impact/metals/1shot_metalhit_06.ogg<br />
* sound/impact/shaky_metal_bangs/mbang_01.wav .. sound/impact/shaky_metal_bangs/mbang_05.wav<br />
* sound/impact/solid/impact_01.ogg<br />
* sound/impact/solid/impact_02.ogg<br />
* sound/impact/solid/impact_03.ogg<br />
* sound/impact/stairs/simpact_04.ogg<br />
* sound/impact/steel/clang_01.ogg<br />
* sound/impact/steel/clang_02.ogg<br />
* sound/impact/steel/clang_03.ogg<br />
* sound/impact/steel/clang_04.wav<br />
* sound/impact/steel/clang_05.ogg<br />
* sound/levels/caverns2/stone_movement_loop.wav<br />
* sound/levels/hell/thunderclap_01a.wav<br />
* sound/levels/hell/thunderclap_02a.wav<br />
* sound/levels/hell/thunderclap_03a.wav<br />
* sound/levels/hell/thunderclap_04a.wav<br />
* sound/machinery/loop_machinery_03.wav<br />
* sound/machinery/machines/loop_airpump_02.wav<br />
* sound/machinery/machines/loop_machinery_01.ogg<br />
* sound/machinery/machines/loop_machinery_02.ogg<br />
* sound/machinery/steamchuffs/steamchuff_01.ogg<br />
* sound/machinery/steamchuffs/steamchuff_02.ogg<br />
* sound/monsters/cacodemon/caco_chatter1.wav .. sound/monsters/cacodemon/caco_chatter6.wav<br />
* sound/monsters/cacodemon/pimpact_01.wav .. sound/monsters/cacodemon/pimpact_04.wav<br />
* sound/monsters/lost_soul/chatter_01.wav .. sound/monsters/lost_soul/chatter_03.wav<br />
* sound/monsters/maggot/distant_screams_01.ogg<br />
* sound/monsters/maggot/distant_screams_03.ogg<br />
* sound/monsters/maggot/idle_01.wav<br />
* sound/monsters/maggot/idle_02.wav<br />
* sound/monsters/maggot/idle_03.wav<br />
* sound/monsters/maggot/idle_04.wav<br />
* sound/monsters/trite/death21.wav<br />
* sound/monsters/trite/death22.wav<br />
* sound/monsters/trite/death23.wav<br />
* sound/monsters/trite/pain8.wav<br />
* sound/monsters/trite/pain9.wav<br />
* sound/monsters/trite/sight1.wav<br />
* sound/monsters/trite/sight3.wav<br />
* sound/monsters/trite/sight5.wav<br />
* sound/movers/_general_movement/m3_end.wav<br />
* sound/movers/_general_movement/m3_loop.wav<br />
* sound/movers/_general_movement/m3_start.wav<br />
* sound/sfx/voices/generic/brush01.ogg<br />
* sound/stress/1shot_creaking_02.wav<br />
* sound/weapons/casings/small_metal_02.wav<br />
* sound/weapons/explosions/explode_01.wav<br />
* sound/weapons/explosions/impexp_03.wav<br />
* sound/weapons/explosions/impexp_04.wav<br />
* sound/weapons/explosions/impexp_05.wav<br />
* sound/weapons/explosions/impexp_06.wav<br />
* sound/weapons/impacts/bullet_metal/metalimpact_04.wav<br />
* sound/xian/creepy/prayer/deliver_us.ogg<br />
* sound/xian/foley_sessions/coughs/cough_01.ogg .. sound/xian/foley_sessions/coughs/cough_05.ogg<br />
* <strike>sound/xian/foley_sessions/metals_small/lowtink_01.ogg .. sound/xian/foley_sessions/metals_small/lowtink_03.ogg</strike><br />
* sound/xian/roomtones2/dangerlow_01.wav<br />
* sound/xian/suspense/loop_suspense_07.wav<br />
* steam_01.wav<br />
* steelswing_01.wav<br />
* stone_movement_end.wav<br />
* teleport_machine_idle.wav<br />
* tincan.wav<br />
* vault_clock_ambient.wav<br />
* wind_01.wav<br />
* wind_02.wav<br />
<br />
==== Unused, but generating warnings ====<br />
<br />
These are probably automatically loaded, but never used and can be removed in the code:<br />
<br />
* player_sounds_doublevision.wav<br />
* player_sounds_guienter.wav<br />
* player_sounds_guiexit.wav<br />
* player_sounds_heartbeat.wav<br />
* player_sounds_heartbeat_dying.wav<br />
* player_sounds_hitflesh.wav<br />
* player_sounds_skipcinematic.wav<br />
* player_sounds_teleportexit.wav<br />
* player_sounds_teleportstart.wav<br />
* player_sounds_thud.wav<br />
<br />
=== AI ===<br />
<br />
* Zombie + animations<br />
* Joint 'Shoulders' not found for 'head_joint' on 'atdm_ai_undead_zombie_a...<br />
* models/md5/monsters/skeleton/skeleton.md5mesh<br />
<br />
=== Animations ===<br />
<br />
* models/md5/characters/npcs/zheads/z1idle.md5anim<br />
* models/md5/chars/af_pose.md5anim<br />
* models/md5/environments/hellchain.md5anim<br />
* models/md5/environments/swinglight_round.md5anim<br />
* models/md5/monsters/imp/initial.md5anim<br />
<br />
=== AF (Articulated Figures) ===<br />
<br />
* monster_demon_imp<br />
* monster_zombie_base<br />
* monster_zombie_bernie<br />
<br />
=== Models ===<br />
<br />
Static and moveable models, not counting meshes (for AI). These are missing and need to be redone:<br />
<br />
* models/gibs/brain_2xb.lwo<br />
* models/gibs/gib_left_arm.lwo<br />
* models/gibs/gib_left_leg.lwo<br />
* models/gibs/gib_right_foot.lwo<br />
* models/gibs/gib_torso.lwo<br />
* models/gibs/left_waist_pork.lwo<br />
* models/gibs/lup_leg_pork.lwo<br />
* models/mapobjects/caves/caverock1.ase<br />
* models/mapobjects/hell/mancroom/bars.lwo<br />
* models/mapobjects/lights/cagelight/cagelight.lwo<br />
* models/mapobjects/tables/bunkbed/mattress.lwo<br />
<br />
This one is a place holder for a quiver model, so we need a quiver instead this:<br />
<br />
* models/items/shells_ammo/shells_large.lwo<br />
<br />
We do miss some models altogether, and some models are modified versions of D3 meshes.<br />
They won't throw an error because they're included in the mod, but they can't be left in if TDM is going standalone:<br />
<br />
* pick-axe<br />
* wooden tray<br />
* several chain models<br />
* skull01 model<br />
* candle textures (and possibly mesh)<br />
* jar<br />
* noblewoman's legs<br />
* beggar's arms and legs<br />
* werebeast body<br />
* Sykes head and textures<br />
* head08 mesh and textures<br />
* head06 mesh and textures<br />
* head01 mesh and textures<br />
<br />
== See also ==<br />
<br />
* [[IdTech4 Open Source]]<br />
* [[Standalone Progress]]<br />
<br />
{{standalone}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Missing_assets_for_standalone_TDM&diff=15760Missing assets for standalone TDM2012-11-09T06:17:21Z<p>Angua: /* Sounds */</p>
<hr />
<div><!-- search keywords: standalone free doom3 doom stand-alone--><br />
This page contains a list of assets that need to be replaced to make The Dark Mod stand-alone, that is to be able to play missions without having Doom 3 installed.<br />
<br />
{{infobox|bg=#e06060|fg=#ffff30|This list is incomplete!}}<br />
<br />
<br />
== Missing assets ==<br />
<br />
=== Textures ===<br />
<br />
The material shaders have now all been added, so we just miss the textures:<br />
<br />
Missing for the new SL (these might be shaders, not textures, it is hard to tell):<br />
<br />
* textures/decals/a_stain01_d01a<br />
* textures/decals/ballburn01_fx<br />
* textures/decals/dirtblast<br />
* textures/decals/dsplat5<br />
* textures/decals/fgrill2<br />
* textures/decals/genericdamage<br />
* textures/decals/graffiti2<br />
* textures/decals/handprint02<br />
* textures/decals/mcu_slimestain<br />
* textures/decals/scorch2<br />
* textures/decals/sdirt10<br />
* textures/decals/sdirt11<br />
* textures/decals/splat11<br />
* textures/decals/stain01b<br />
* textures/decals/stain02<br />
* textures/glass/glass1<br />
* textures/glass/outdoor_glass1fx<br />
* textures/hell/dirt02<br />
* textures/hell/dirt02_s<br />
* textures/particles/bloodspray<br />
* textures/particles/boomboom<br />
* textures/particles/droppuddle<br />
* textures/particles/fbeam<br />
* textures/particles/pfirebig<br />
* textures/particles/pfiresmall2<br />
* textures/particles/preamble<br />
* textures/particles/snowball<br />
<br />
Missing otherwise:<br />
<br />
* textures/decals/ballburn01<br />
* textures/decals/bloodspray<br />
* textures/decals/bulleth02<br />
* textures/decals/fly<br />
* textures/decals/hurt02<br />
* textures/decals/sdirt11a<br />
* textures/decals/splat1 .. textures/decals/splat9<br />
* textures/decals/stain01b<br />
* textures/decals/stain03<br />
* textures/decals/stainwall<br />
* textures/decals/stainwallfade<br />
* textures/glass/glass1<br />
* textures/glass/outdoor_glass1fx<br />
* textures/hell/dirt02<br />
* textures/hell/dirt02_s<br />
* textures/hell/wood1<br />
* textures/hell/lava1<br />
* textures/particles/billow3_glow<br />
* textures/particles/billow_glow<br />
* textures/particles/boomboom<br />
* textures/particles/boomboom2<br />
* textures/particles/boomboom3<br />
* textures/particles/drop2<br />
* textures/particles/droppuddle<br />
* textures/particles/dust<br />
* textures/particles/fbeam<br />
* textures/particles/pfiresmall2<br />
* textures/particles/plasma<br />
* textures/particles/preamble<br />
* textures/particles/snowball<br />
* textures/particles/spark3<br />
* textures/particles/s_lightning2_whi<br />
* textures/particles/s_lightning_masked<br />
* textures/sfx/vp1<br />
* textures/sfx/vpring3<br />
* thunderlight1<br />
* thunderlight2<br />
* thunderlightsky1<br />
* thunderlightsky2<br />
* topc<br />
<br />
=== Cube maps ===<br />
<br />
* env/gen2<br />
<br />
=== Sounds ===<br />
<br />
* _default.wav<br />
* activate_airpump_02.wav<br />
* admin_impdoor_creak.wav<br />
* alarm.wav<br />
* ambient_metal_stresses.wav<br />
* bodyparts.wav<br />
* bones_fall.wav<br />
* book_impact.wav<br />
* breakable_light_hum.wav<br />
* bridge_up_speaker.wav<br />
* bullet_impact_flesh.wav<br />
* bullet_impact_stone.wav<br />
* bullet_impact_wood.wav<br />
* <strike>burger_impact.wav</strike><br />
* caco_projectile.wav<br />
* cage_elevatordoor_close.wav<br />
* cage_elevatordoor_open.wav<br />
* ceiling_tiles.wav<br />
* cpu_m3_loop.wav<br />
* d3dm5_generator_off.wav<br />
* d3dm5_generator_on.wav<br />
* default_door_unlocked.wav (this is only used as temprorary sound for our entityDef atdm:alarm_sound entity... probably doesn't need a similar replacement)<br />
* e3_metalbash_01.wav<br />
* elevator_moving_loop.wav<br />
* fire_torch01_small.wav<br />
* fist_impact.wav<br />
* glass_bullethole.wav<br />
* glass_shatter.wav<br />
* hell_gatelower.wav<br />
* hh_door_movement_1.wav<br />
* light_flicker_104.wav<br />
* light_flicker_124.wav<br />
* light_hum_102.wav<br />
* loop_hum_01.wav<br />
* m3_loop.wav<br />
* m3_start.wav<br />
* m3_stop.wav<br />
* metalbounce_1.wav<br />
* monster_demon_archvile_die.wav<br />
* monster_demon_archvile_pain.wav<br />
* monster_demon_imp_fireball_explode.wav<br />
* monster_demon_imp_fireball_flight.wav<br />
* monster_demon_imp_melee_hit.wav<br />
* monster_demon_imp_melee_miss.wav<br />
* monster_demon_imp_thud.wav<br />
* monster_demon_maggot_melee2.wav<br />
* monster_demon_pinky_sight2.wav<br />
* monster_demon_tick_footstep.wav<br />
* monster_demon_trite_chatter.wav<br />
* monster_demon_trite_chatter_combat.wav<br />
* monster_demon_trite_death.wav<br />
* monster_demon_trite_melee.wav<br />
* monster_demon_trite_pain.wav<br />
* monster_demon_trite_sight.wav<br />
* <strike>monster_zombie_boney_chatter.wav</strike><br />
* <strike>monster_zombie_boney_chatter_combat.wav</strike><br />
* <strike>monster_zombie_boney_die.wav</strike><br />
* monster_zombie_boney_pain.wav<br />
* monster_zombie_boney_sight.wav<br />
* monster_zombie_maint_footstep.wav<br />
* monster_zombie_maint_thud.wav<br />
* null.wav<br />
* paper_impact.wav<br />
* pool_ball_impact.wav<br />
* rec1_steamchuff.wav<br />
* sound/ambient/loop_rumble_01.wav<br />
* <strike>sound/doors/hell/open_02.wav</strike><br />
* sound/doors/large/hugedoor_01_open.wav<br />
* sound/ed/admin/light_break.wav<br />
* sound/ed/archvile/breath1.wav .. sound/ed/archvile/breath3.wav<br />
* sound/ed/cherub/evillaugh2.ogg<br />
* sound/ed/cyberdemon/chatter1.wav .. sound/ed/cyberdemon/chatter4.wav<br />
* sound/ed/elevator/elev_end.wav<br />
* sound/ed/elevator/elev_start.wav<br />
* sound/ed/imp/alert_test32.wav<br />
* sound/ed/imp/alert_test33.wav<br />
* sound/ed/imp/alert_test34.wav<br />
* sound/ed/imp/alert_test39.wav<br />
* sound/ed/maggot/hiss3h2.ogg<br />
* sound/ed/pinky/pain_test1.wav .. sound/ed/pinky/pain_test7.wav<br />
* sound/ed/pinky3/death_test1.wav .. sound/ed/pinky3/death_test5.wav<br />
* sound/ed/pinky3/idle_test1.wav .. sound/ed/pinky3/idle_test4.wav<br />
* sound/ed/pinky3/sight3_test1.wav .. sound/ed/pinky3/sight3_test4.wav<br />
* sound/ed/pinky3/sight_test21.wav<br />
* sound/ed/pinky3/sight_test22.wav<br />
* sound/ed/pinky3/sight_test23.wav<br />
* sound/ed/player/player_land2.ogg<br />
* sound/ed/sfx/barrel1.ogg .. sound/ed/sfx/barrel5.ogg<br />
* sound/ed/sfx/wrench_impact1.ogg<br />
* sound/ed/sfx/wrench_impact2.ogg<br />
* sound/ed/spook/ohgodplease.ogg<br />
* sound/ed/spook/please.ogg<br />
* sound/ed/tick/chirp1.ogg .. sound/ed/tick/chirp6.ogg<br />
* sound/ed/tick/tick_death1.ogg .. sound/ed/tick/tick_death3.ogg<br />
* sound/ed/tick/tick_pain1.ogg .. sound/ed/tick/tick_pain4.ogg<br />
* <strike>sound/ed/tick/tick_walk1.wav .. sound/ed/tick/tick_walk6.wav</strike><br />
* sound/ed/trite/breath_hollow_deep4.ogg<br />
* sound/ed/trite/breath_hollow_raspy1.ogg<br />
* sound/ed/trite/breath_throaty6.ogg<br />
* sound/impact/ambient_impacts/emetal_01.wav .. sound/impact/ambient_impacts/emetal_05.wav<br />
* sound/impact/boxes/boxfall_18.ogg<br />
* sound/impact/crash/glasscrash_01.ogg .. sound/impact/crash/glasscrash_04.ogg<br />
* sound/impact/metal_doors/slam_01.ogg<br />
* sound/impact/metal_doors/slam_08_boomy.wav<br />
* sound/impact/metals/1shot_metalhit_01.ogg<br />
* sound/impact/metals/1shot_metalhit_03.ogg<br />
* sound/impact/metals/1shot_metalhit_06.ogg<br />
* sound/impact/shaky_metal_bangs/mbang_01.wav .. sound/impact/shaky_metal_bangs/mbang_05.wav<br />
* sound/impact/solid/impact_01.ogg<br />
* sound/impact/solid/impact_02.ogg<br />
* sound/impact/solid/impact_03.ogg<br />
* sound/impact/stairs/simpact_04.ogg<br />
* sound/impact/steel/clang_01.ogg<br />
* sound/impact/steel/clang_02.ogg<br />
* sound/impact/steel/clang_03.ogg<br />
* sound/impact/steel/clang_04.wav<br />
* sound/impact/steel/clang_05.ogg<br />
* sound/levels/caverns2/stone_movement_loop.wav<br />
* sound/levels/hell/thunderclap_01a.wav<br />
* sound/levels/hell/thunderclap_02a.wav<br />
* sound/levels/hell/thunderclap_03a.wav<br />
* sound/levels/hell/thunderclap_04a.wav<br />
* sound/machinery/loop_machinery_03.wav<br />
* sound/machinery/machines/loop_airpump_02.wav<br />
* sound/machinery/machines/loop_machinery_01.ogg<br />
* sound/machinery/machines/loop_machinery_02.ogg<br />
* sound/machinery/steamchuffs/steamchuff_01.ogg<br />
* sound/machinery/steamchuffs/steamchuff_02.ogg<br />
* sound/monsters/cacodemon/caco_chatter1.wav .. sound/monsters/cacodemon/caco_chatter6.wav<br />
* sound/monsters/cacodemon/pimpact_01.wav .. sound/monsters/cacodemon/pimpact_04.wav<br />
* sound/monsters/lost_soul/chatter_01.wav .. sound/monsters/lost_soul/chatter_03.wav<br />
* sound/monsters/maggot/distant_screams_01.ogg<br />
* sound/monsters/maggot/distant_screams_03.ogg<br />
* sound/monsters/maggot/idle_01.wav<br />
* sound/monsters/maggot/idle_02.wav<br />
* sound/monsters/maggot/idle_03.wav<br />
* sound/monsters/maggot/idle_04.wav<br />
* sound/monsters/trite/death21.wav<br />
* sound/monsters/trite/death22.wav<br />
* sound/monsters/trite/death23.wav<br />
* sound/monsters/trite/pain8.wav<br />
* sound/monsters/trite/pain9.wav<br />
* sound/monsters/trite/sight1.wav<br />
* sound/monsters/trite/sight3.wav<br />
* sound/monsters/trite/sight5.wav<br />
* sound/movers/_general_movement/m3_end.wav<br />
* sound/movers/_general_movement/m3_loop.wav<br />
* sound/movers/_general_movement/m3_start.wav<br />
* sound/sfx/voices/generic/brush01.ogg<br />
* sound/stress/1shot_creaking_02.wav<br />
* sound/weapons/casings/small_metal_02.wav<br />
* sound/weapons/explosions/explode_01.wav<br />
* sound/weapons/explosions/impexp_03.wav<br />
* sound/weapons/explosions/impexp_04.wav<br />
* sound/weapons/explosions/impexp_05.wav<br />
* sound/weapons/explosions/impexp_06.wav<br />
* sound/weapons/impacts/bullet_metal/metalimpact_04.wav<br />
* sound/xian/creepy/prayer/deliver_us.ogg<br />
* sound/xian/foley_sessions/coughs/cough_01.ogg .. sound/xian/foley_sessions/coughs/cough_05.ogg<br />
* <strike>sound/xian/foley_sessions/metals_small/lowtink_01.ogg .. sound/xian/foley_sessions/metals_small/lowtink_03.ogg</strike><br />
* sound/xian/roomtones2/dangerlow_01.wav<br />
* sound/xian/suspense/loop_suspense_07.wav<br />
* steam_01.wav<br />
* steelswing_01.wav<br />
* stone_movement_end.wav<br />
* teleport_machine_idle.wav<br />
* tincan.wav<br />
* vault_clock_ambient.wav<br />
* wind_01.wav<br />
* wind_02.wav<br />
<br />
==== Unused, but generating warnings ====<br />
<br />
These are probably automatically loaded, but never used and can be removed in the code:<br />
<br />
* player_sounds_doublevision.wav<br />
* player_sounds_guienter.wav<br />
* player_sounds_guiexit.wav<br />
* player_sounds_heartbeat.wav<br />
* player_sounds_heartbeat_dying.wav<br />
* player_sounds_hitflesh.wav<br />
* player_sounds_skipcinematic.wav<br />
* player_sounds_teleportexit.wav<br />
* player_sounds_teleportstart.wav<br />
* player_sounds_thud.wav<br />
<br />
=== AI ===<br />
<br />
* Zombie + animations<br />
* Joint 'Shoulders' not found for 'head_joint' on 'atdm_ai_undead_zombie_a...<br />
* models/md5/monsters/skeleton/skeleton.md5mesh<br />
<br />
=== Animations ===<br />
<br />
* models/md5/characters/npcs/zheads/z1idle.md5anim<br />
* models/md5/chars/af_pose.md5anim<br />
* models/md5/environments/hellchain.md5anim<br />
* models/md5/environments/swinglight_round.md5anim<br />
* models/md5/monsters/imp/initial.md5anim<br />
<br />
=== AF (Articulated Figures) ===<br />
<br />
* monster_demon_imp<br />
* monster_zombie_base<br />
* monster_zombie_bernie<br />
<br />
=== Models ===<br />
<br />
Static and moveable models, not counting meshes (for AI). These are missing and need to be redone:<br />
<br />
* models/gibs/brain_2xb.lwo<br />
* models/gibs/gib_left_arm.lwo<br />
* models/gibs/gib_left_leg.lwo<br />
* models/gibs/gib_right_foot.lwo<br />
* models/gibs/gib_torso.lwo<br />
* models/gibs/left_waist_pork.lwo<br />
* models/gibs/lup_leg_pork.lwo<br />
* models/mapobjects/caves/caverock1.ase<br />
* models/mapobjects/hell/mancroom/bars.lwo<br />
* models/mapobjects/lights/cagelight/cagelight.lwo<br />
* models/mapobjects/tables/bunkbed/mattress.lwo<br />
<br />
This one is a place holder for a quiver model, so we need a quiver instead this:<br />
<br />
* models/items/shells_ammo/shells_large.lwo<br />
<br />
We do miss some models altogether, and some models are modified versions of D3 meshes.<br />
They won't throw an error because they're included in the mod, but they can't be left in if TDM is going standalone:<br />
<br />
* pick-axe<br />
* wooden tray<br />
* several chain models<br />
* skull01 model<br />
* candle textures (and possibly mesh)<br />
* jar<br />
* noblewoman's legs<br />
* beggar's arms and legs<br />
* werebeast body<br />
* Sykes head and textures<br />
* head08 mesh and textures<br />
* head06 mesh and textures<br />
* head01 mesh and textures<br />
<br />
== See also ==<br />
<br />
* [[IdTech4 Open Source]]<br />
* [[Standalone Progress]]<br />
<br />
{{standalone}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Missing_assets_for_standalone_TDM&diff=15759Missing assets for standalone TDM2012-11-09T06:08:54Z<p>Angua: /* Sounds */</p>
<hr />
<div><!-- search keywords: standalone free doom3 doom stand-alone--><br />
This page contains a list of assets that need to be replaced to make The Dark Mod stand-alone, that is to be able to play missions without having Doom 3 installed.<br />
<br />
{{infobox|bg=#e06060|fg=#ffff30|This list is incomplete!}}<br />
<br />
<br />
== Missing assets ==<br />
<br />
=== Textures ===<br />
<br />
The material shaders have now all been added, so we just miss the textures:<br />
<br />
Missing for the new SL (these might be shaders, not textures, it is hard to tell):<br />
<br />
* textures/decals/a_stain01_d01a<br />
* textures/decals/ballburn01_fx<br />
* textures/decals/dirtblast<br />
* textures/decals/dsplat5<br />
* textures/decals/fgrill2<br />
* textures/decals/genericdamage<br />
* textures/decals/graffiti2<br />
* textures/decals/handprint02<br />
* textures/decals/mcu_slimestain<br />
* textures/decals/scorch2<br />
* textures/decals/sdirt10<br />
* textures/decals/sdirt11<br />
* textures/decals/splat11<br />
* textures/decals/stain01b<br />
* textures/decals/stain02<br />
* textures/glass/glass1<br />
* textures/glass/outdoor_glass1fx<br />
* textures/hell/dirt02<br />
* textures/hell/dirt02_s<br />
* textures/particles/bloodspray<br />
* textures/particles/boomboom<br />
* textures/particles/droppuddle<br />
* textures/particles/fbeam<br />
* textures/particles/pfirebig<br />
* textures/particles/pfiresmall2<br />
* textures/particles/preamble<br />
* textures/particles/snowball<br />
<br />
Missing otherwise:<br />
<br />
* textures/decals/ballburn01<br />
* textures/decals/bloodspray<br />
* textures/decals/bulleth02<br />
* textures/decals/fly<br />
* textures/decals/hurt02<br />
* textures/decals/sdirt11a<br />
* textures/decals/splat1 .. textures/decals/splat9<br />
* textures/decals/stain01b<br />
* textures/decals/stain03<br />
* textures/decals/stainwall<br />
* textures/decals/stainwallfade<br />
* textures/glass/glass1<br />
* textures/glass/outdoor_glass1fx<br />
* textures/hell/dirt02<br />
* textures/hell/dirt02_s<br />
* textures/hell/wood1<br />
* textures/hell/lava1<br />
* textures/particles/billow3_glow<br />
* textures/particles/billow_glow<br />
* textures/particles/boomboom<br />
* textures/particles/boomboom2<br />
* textures/particles/boomboom3<br />
* textures/particles/drop2<br />
* textures/particles/droppuddle<br />
* textures/particles/dust<br />
* textures/particles/fbeam<br />
* textures/particles/pfiresmall2<br />
* textures/particles/plasma<br />
* textures/particles/preamble<br />
* textures/particles/snowball<br />
* textures/particles/spark3<br />
* textures/particles/s_lightning2_whi<br />
* textures/particles/s_lightning_masked<br />
* textures/sfx/vp1<br />
* textures/sfx/vpring3<br />
* thunderlight1<br />
* thunderlight2<br />
* thunderlightsky1<br />
* thunderlightsky2<br />
* topc<br />
<br />
=== Cube maps ===<br />
<br />
* env/gen2<br />
<br />
=== Sounds ===<br />
<br />
* _default.wav<br />
* activate_airpump_02.wav<br />
* admin_impdoor_creak.wav<br />
* alarm.wav<br />
* ambient_metal_stresses.wav<br />
* bodyparts.wav<br />
* bones_fall.wav<br />
* book_impact.wav<br />
* breakable_light_hum.wav<br />
* bridge_up_speaker.wav<br />
* bullet_impact_flesh.wav<br />
* bullet_impact_stone.wav<br />
* bullet_impact_wood.wav<br />
* <strike>burger_impact.wav</strike><br />
* caco_projectile.wav<br />
* cage_elevatordoor_close.wav<br />
* cage_elevatordoor_open.wav<br />
* ceiling_tiles.wav<br />
* cpu_m3_loop.wav<br />
* d3dm5_generator_off.wav<br />
* d3dm5_generator_on.wav<br />
* default_door_unlocked.wav (this is only used as temprorary sound for our entityDef atdm:alarm_sound entity... probably doesn't need a similar replacement)<br />
* e3_metalbash_01.wav<br />
* elevator_moving_loop.wav<br />
* fire_torch01_small.wav<br />
* fist_impact.wav<br />
* glass_bullethole.wav<br />
* glass_shatter.wav<br />
* hell_gatelower.wav<br />
* hh_door_movement_1.wav<br />
* light_flicker_104.wav<br />
* light_flicker_124.wav<br />
* light_hum_102.wav<br />
* loop_hum_01.wav<br />
* m3_loop.wav<br />
* m3_start.wav<br />
* m3_stop.wav<br />
* metalbounce_1.wav<br />
* monster_demon_archvile_die.wav<br />
* monster_demon_archvile_pain.wav<br />
* monster_demon_imp_fireball_explode.wav<br />
* monster_demon_imp_fireball_flight.wav<br />
* monster_demon_imp_melee_hit.wav<br />
* monster_demon_imp_melee_miss.wav<br />
* monster_demon_imp_thud.wav<br />
* monster_demon_maggot_melee2.wav<br />
* monster_demon_pinky_sight2.wav<br />
* monster_demon_tick_footstep.wav<br />
* monster_demon_trite_chatter.wav<br />
* monster_demon_trite_chatter_combat.wav<br />
* monster_demon_trite_death.wav<br />
* monster_demon_trite_melee.wav<br />
* monster_demon_trite_pain.wav<br />
* monster_demon_trite_sight.wav<br />
* <strike>monster_zombie_boney_chatter.wav</strike><br />
* monster_zombie_boney_chatter_combat.wav<br />
* monster_zombie_boney_die.wav<br />
* monster_zombie_boney_pain.wav<br />
* monster_zombie_boney_sight.wav<br />
* monster_zombie_maint_footstep.wav<br />
* monster_zombie_maint_thud.wav<br />
* null.wav<br />
* paper_impact.wav<br />
* pool_ball_impact.wav<br />
* rec1_steamchuff.wav<br />
* sound/ambient/loop_rumble_01.wav<br />
* <strike>sound/doors/hell/open_02.wav</strike><br />
* sound/doors/large/hugedoor_01_open.wav<br />
* sound/ed/admin/light_break.wav<br />
* sound/ed/archvile/breath1.wav .. sound/ed/archvile/breath3.wav<br />
* sound/ed/cherub/evillaugh2.ogg<br />
* sound/ed/cyberdemon/chatter1.wav .. sound/ed/cyberdemon/chatter4.wav<br />
* sound/ed/elevator/elev_end.wav<br />
* sound/ed/elevator/elev_start.wav<br />
* sound/ed/imp/alert_test32.wav<br />
* sound/ed/imp/alert_test33.wav<br />
* sound/ed/imp/alert_test34.wav<br />
* sound/ed/imp/alert_test39.wav<br />
* sound/ed/maggot/hiss3h2.ogg<br />
* sound/ed/pinky/pain_test1.wav .. sound/ed/pinky/pain_test7.wav<br />
* sound/ed/pinky3/death_test1.wav .. sound/ed/pinky3/death_test5.wav<br />
* sound/ed/pinky3/idle_test1.wav .. sound/ed/pinky3/idle_test4.wav<br />
* sound/ed/pinky3/sight3_test1.wav .. sound/ed/pinky3/sight3_test4.wav<br />
* sound/ed/pinky3/sight_test21.wav<br />
* sound/ed/pinky3/sight_test22.wav<br />
* sound/ed/pinky3/sight_test23.wav<br />
* sound/ed/player/player_land2.ogg<br />
* sound/ed/sfx/barrel1.ogg .. sound/ed/sfx/barrel5.ogg<br />
* sound/ed/sfx/wrench_impact1.ogg<br />
* sound/ed/sfx/wrench_impact2.ogg<br />
* sound/ed/spook/ohgodplease.ogg<br />
* sound/ed/spook/please.ogg<br />
* sound/ed/tick/chirp1.ogg .. sound/ed/tick/chirp6.ogg<br />
* sound/ed/tick/tick_death1.ogg .. sound/ed/tick/tick_death3.ogg<br />
* sound/ed/tick/tick_pain1.ogg .. sound/ed/tick/tick_pain4.ogg<br />
* <strike>sound/ed/tick/tick_walk1.wav .. sound/ed/tick/tick_walk6.wav</strike><br />
* sound/ed/trite/breath_hollow_deep4.ogg<br />
* sound/ed/trite/breath_hollow_raspy1.ogg<br />
* sound/ed/trite/breath_throaty6.ogg<br />
* sound/impact/ambient_impacts/emetal_01.wav .. sound/impact/ambient_impacts/emetal_05.wav<br />
* sound/impact/boxes/boxfall_18.ogg<br />
* sound/impact/crash/glasscrash_01.ogg .. sound/impact/crash/glasscrash_04.ogg<br />
* sound/impact/metal_doors/slam_01.ogg<br />
* sound/impact/metal_doors/slam_08_boomy.wav<br />
* sound/impact/metals/1shot_metalhit_01.ogg<br />
* sound/impact/metals/1shot_metalhit_03.ogg<br />
* sound/impact/metals/1shot_metalhit_06.ogg<br />
* sound/impact/shaky_metal_bangs/mbang_01.wav .. sound/impact/shaky_metal_bangs/mbang_05.wav<br />
* sound/impact/solid/impact_01.ogg<br />
* sound/impact/solid/impact_02.ogg<br />
* sound/impact/solid/impact_03.ogg<br />
* sound/impact/stairs/simpact_04.ogg<br />
* sound/impact/steel/clang_01.ogg<br />
* sound/impact/steel/clang_02.ogg<br />
* sound/impact/steel/clang_03.ogg<br />
* sound/impact/steel/clang_04.wav<br />
* sound/impact/steel/clang_05.ogg<br />
* sound/levels/caverns2/stone_movement_loop.wav<br />
* sound/levels/hell/thunderclap_01a.wav<br />
* sound/levels/hell/thunderclap_02a.wav<br />
* sound/levels/hell/thunderclap_03a.wav<br />
* sound/levels/hell/thunderclap_04a.wav<br />
* sound/machinery/loop_machinery_03.wav<br />
* sound/machinery/machines/loop_airpump_02.wav<br />
* sound/machinery/machines/loop_machinery_01.ogg<br />
* sound/machinery/machines/loop_machinery_02.ogg<br />
* sound/machinery/steamchuffs/steamchuff_01.ogg<br />
* sound/machinery/steamchuffs/steamchuff_02.ogg<br />
* sound/monsters/cacodemon/caco_chatter1.wav .. sound/monsters/cacodemon/caco_chatter6.wav<br />
* sound/monsters/cacodemon/pimpact_01.wav .. sound/monsters/cacodemon/pimpact_04.wav<br />
* sound/monsters/lost_soul/chatter_01.wav .. sound/monsters/lost_soul/chatter_03.wav<br />
* sound/monsters/maggot/distant_screams_01.ogg<br />
* sound/monsters/maggot/distant_screams_03.ogg<br />
* sound/monsters/maggot/idle_01.wav<br />
* sound/monsters/maggot/idle_02.wav<br />
* sound/monsters/maggot/idle_03.wav<br />
* sound/monsters/maggot/idle_04.wav<br />
* sound/monsters/trite/death21.wav<br />
* sound/monsters/trite/death22.wav<br />
* sound/monsters/trite/death23.wav<br />
* sound/monsters/trite/pain8.wav<br />
* sound/monsters/trite/pain9.wav<br />
* sound/monsters/trite/sight1.wav<br />
* sound/monsters/trite/sight3.wav<br />
* sound/monsters/trite/sight5.wav<br />
* sound/movers/_general_movement/m3_end.wav<br />
* sound/movers/_general_movement/m3_loop.wav<br />
* sound/movers/_general_movement/m3_start.wav<br />
* sound/sfx/voices/generic/brush01.ogg<br />
* sound/stress/1shot_creaking_02.wav<br />
* sound/weapons/casings/small_metal_02.wav<br />
* sound/weapons/explosions/explode_01.wav<br />
* sound/weapons/explosions/impexp_03.wav<br />
* sound/weapons/explosions/impexp_04.wav<br />
* sound/weapons/explosions/impexp_05.wav<br />
* sound/weapons/explosions/impexp_06.wav<br />
* sound/weapons/impacts/bullet_metal/metalimpact_04.wav<br />
* sound/xian/creepy/prayer/deliver_us.ogg<br />
* sound/xian/foley_sessions/coughs/cough_01.ogg .. sound/xian/foley_sessions/coughs/cough_05.ogg<br />
* <strike>sound/xian/foley_sessions/metals_small/lowtink_01.ogg .. sound/xian/foley_sessions/metals_small/lowtink_03.ogg</strike><br />
* sound/xian/roomtones2/dangerlow_01.wav<br />
* sound/xian/suspense/loop_suspense_07.wav<br />
* steam_01.wav<br />
* steelswing_01.wav<br />
* stone_movement_end.wav<br />
* teleport_machine_idle.wav<br />
* tincan.wav<br />
* vault_clock_ambient.wav<br />
* wind_01.wav<br />
* wind_02.wav<br />
<br />
==== Unused, but generating warnings ====<br />
<br />
These are probably automatically loaded, but never used and can be removed in the code:<br />
<br />
* player_sounds_doublevision.wav<br />
* player_sounds_guienter.wav<br />
* player_sounds_guiexit.wav<br />
* player_sounds_heartbeat.wav<br />
* player_sounds_heartbeat_dying.wav<br />
* player_sounds_hitflesh.wav<br />
* player_sounds_skipcinematic.wav<br />
* player_sounds_teleportexit.wav<br />
* player_sounds_teleportstart.wav<br />
* player_sounds_thud.wav<br />
<br />
=== AI ===<br />
<br />
* Zombie + animations<br />
* Joint 'Shoulders' not found for 'head_joint' on 'atdm_ai_undead_zombie_a...<br />
* models/md5/monsters/skeleton/skeleton.md5mesh<br />
<br />
=== Animations ===<br />
<br />
* models/md5/characters/npcs/zheads/z1idle.md5anim<br />
* models/md5/chars/af_pose.md5anim<br />
* models/md5/environments/hellchain.md5anim<br />
* models/md5/environments/swinglight_round.md5anim<br />
* models/md5/monsters/imp/initial.md5anim<br />
<br />
=== AF (Articulated Figures) ===<br />
<br />
* monster_demon_imp<br />
* monster_zombie_base<br />
* monster_zombie_bernie<br />
<br />
=== Models ===<br />
<br />
Static and moveable models, not counting meshes (for AI). These are missing and need to be redone:<br />
<br />
* models/gibs/brain_2xb.lwo<br />
* models/gibs/gib_left_arm.lwo<br />
* models/gibs/gib_left_leg.lwo<br />
* models/gibs/gib_right_foot.lwo<br />
* models/gibs/gib_torso.lwo<br />
* models/gibs/left_waist_pork.lwo<br />
* models/gibs/lup_leg_pork.lwo<br />
* models/mapobjects/caves/caverock1.ase<br />
* models/mapobjects/hell/mancroom/bars.lwo<br />
* models/mapobjects/lights/cagelight/cagelight.lwo<br />
* models/mapobjects/tables/bunkbed/mattress.lwo<br />
<br />
This one is a place holder for a quiver model, so we need a quiver instead this:<br />
<br />
* models/items/shells_ammo/shells_large.lwo<br />
<br />
We do miss some models altogether, and some models are modified versions of D3 meshes.<br />
They won't throw an error because they're included in the mod, but they can't be left in if TDM is going standalone:<br />
<br />
* pick-axe<br />
* wooden tray<br />
* several chain models<br />
* skull01 model<br />
* candle textures (and possibly mesh)<br />
* jar<br />
* noblewoman's legs<br />
* beggar's arms and legs<br />
* werebeast body<br />
* Sykes head and textures<br />
* head08 mesh and textures<br />
* head06 mesh and textures<br />
* head01 mesh and textures<br />
<br />
== See also ==<br />
<br />
* [[IdTech4 Open Source]]<br />
* [[Standalone Progress]]<br />
<br />
{{standalone}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Missing_assets_for_standalone_TDM&diff=15758Missing assets for standalone TDM2012-11-06T13:52:39Z<p>Angua: /* Sounds */</p>
<hr />
<div><!-- search keywords: standalone free doom3 doom stand-alone--><br />
This page contains a list of assets that need to be replaced to make The Dark Mod stand-alone, that is to be able to play missions without having Doom 3 installed.<br />
<br />
{{infobox|bg=#e06060|fg=#ffff30|This list is incomplete!}}<br />
<br />
<br />
== Missing assets ==<br />
<br />
=== Textures ===<br />
<br />
The material shaders have now all been added, so we just miss the textures:<br />
<br />
Missing for the new SL (these might be shaders, not textures, it is hard to tell):<br />
<br />
* textures/decals/a_stain01_d01a<br />
* textures/decals/ballburn01_fx<br />
* textures/decals/dirtblast<br />
* textures/decals/dsplat5<br />
* textures/decals/fgrill2<br />
* textures/decals/genericdamage<br />
* textures/decals/graffiti2<br />
* textures/decals/handprint02<br />
* textures/decals/mcu_slimestain<br />
* textures/decals/scorch2<br />
* textures/decals/sdirt10<br />
* textures/decals/sdirt11<br />
* textures/decals/splat11<br />
* textures/decals/stain01b<br />
* textures/decals/stain02<br />
* textures/glass/glass1<br />
* textures/glass/outdoor_glass1fx<br />
* textures/hell/dirt02<br />
* textures/hell/dirt02_s<br />
* textures/particles/bloodspray<br />
* textures/particles/boomboom<br />
* textures/particles/droppuddle<br />
* textures/particles/fbeam<br />
* textures/particles/pfirebig<br />
* textures/particles/pfiresmall2<br />
* textures/particles/preamble<br />
* textures/particles/snowball<br />
<br />
Missing otherwise:<br />
<br />
* textures/decals/ballburn01<br />
* textures/decals/bloodspray<br />
* textures/decals/bulleth02<br />
* textures/decals/fly<br />
* textures/decals/hurt02<br />
* textures/decals/sdirt11a<br />
* textures/decals/splat1 .. textures/decals/splat9<br />
* textures/decals/stain01b<br />
* textures/decals/stain03<br />
* textures/decals/stainwall<br />
* textures/decals/stainwallfade<br />
* textures/glass/glass1<br />
* textures/glass/outdoor_glass1fx<br />
* textures/hell/dirt02<br />
* textures/hell/dirt02_s<br />
* textures/hell/wood1<br />
* textures/hell/lava1<br />
* textures/particles/billow3_glow<br />
* textures/particles/billow_glow<br />
* textures/particles/boomboom<br />
* textures/particles/boomboom2<br />
* textures/particles/boomboom3<br />
* textures/particles/drop2<br />
* textures/particles/droppuddle<br />
* textures/particles/dust<br />
* textures/particles/fbeam<br />
* textures/particles/pfiresmall2<br />
* textures/particles/plasma<br />
* textures/particles/preamble<br />
* textures/particles/snowball<br />
* textures/particles/spark3<br />
* textures/particles/s_lightning2_whi<br />
* textures/particles/s_lightning_masked<br />
* textures/sfx/vp1<br />
* textures/sfx/vpring3<br />
* thunderlight1<br />
* thunderlight2<br />
* thunderlightsky1<br />
* thunderlightsky2<br />
* topc<br />
<br />
=== Cube maps ===<br />
<br />
* env/gen2<br />
<br />
=== Sounds ===<br />
<br />
* _default.wav<br />
* activate_airpump_02.wav<br />
* admin_impdoor_creak.wav<br />
* alarm.wav<br />
* ambient_metal_stresses.wav<br />
* bodyparts.wav<br />
* bones_fall.wav<br />
* book_impact.wav<br />
* breakable_light_hum.wav<br />
* bridge_up_speaker.wav<br />
* bullet_impact_flesh.wav<br />
* bullet_impact_stone.wav<br />
* bullet_impact_wood.wav<br />
* <strike>burger_impact.wav</strike><br />
* caco_projectile.wav<br />
* cage_elevatordoor_close.wav<br />
* cage_elevatordoor_open.wav<br />
* ceiling_tiles.wav<br />
* cpu_m3_loop.wav<br />
* d3dm5_generator_off.wav<br />
* d3dm5_generator_on.wav<br />
* default_door_unlocked.wav (this is only used as temprorary sound for our entityDef atdm:alarm_sound entity... probably doesn't need a similar replacement)<br />
* e3_metalbash_01.wav<br />
* elevator_moving_loop.wav<br />
* fire_torch01_small.wav<br />
* fist_impact.wav<br />
* glass_bullethole.wav<br />
* glass_shatter.wav<br />
* hell_gatelower.wav<br />
* hh_door_movement_1.wav<br />
* light_flicker_104.wav<br />
* light_flicker_124.wav<br />
* light_hum_102.wav<br />
* loop_hum_01.wav<br />
* m3_loop.wav<br />
* m3_start.wav<br />
* m3_stop.wav<br />
* metalbounce_1.wav<br />
* monster_demon_archvile_die.wav<br />
* monster_demon_archvile_pain.wav<br />
* monster_demon_imp_fireball_explode.wav<br />
* monster_demon_imp_fireball_flight.wav<br />
* monster_demon_imp_melee_hit.wav<br />
* monster_demon_imp_melee_miss.wav<br />
* monster_demon_imp_thud.wav<br />
* monster_demon_maggot_melee2.wav<br />
* monster_demon_pinky_sight2.wav<br />
* monster_demon_tick_footstep.wav<br />
* monster_demon_trite_chatter.wav<br />
* monster_demon_trite_chatter_combat.wav<br />
* monster_demon_trite_death.wav<br />
* monster_demon_trite_melee.wav<br />
* monster_demon_trite_pain.wav<br />
* monster_demon_trite_sight.wav<br />
* monster_zombie_boney_chatter.wav<br />
* monster_zombie_boney_chatter_combat.wav<br />
* monster_zombie_boney_die.wav<br />
* monster_zombie_boney_pain.wav<br />
* monster_zombie_boney_sight.wav<br />
* monster_zombie_maint_footstep.wav<br />
* monster_zombie_maint_thud.wav<br />
* null.wav<br />
* paper_impact.wav<br />
* pool_ball_impact.wav<br />
* rec1_steamchuff.wav<br />
* sound/ambient/loop_rumble_01.wav<br />
* <strike>sound/doors/hell/open_02.wav</strike><br />
* sound/doors/large/hugedoor_01_open.wav<br />
* sound/ed/admin/light_break.wav<br />
* sound/ed/archvile/breath1.wav .. sound/ed/archvile/breath3.wav<br />
* sound/ed/cherub/evillaugh2.ogg<br />
* sound/ed/cyberdemon/chatter1.wav .. sound/ed/cyberdemon/chatter4.wav<br />
* sound/ed/elevator/elev_end.wav<br />
* sound/ed/elevator/elev_start.wav<br />
* sound/ed/imp/alert_test32.wav<br />
* sound/ed/imp/alert_test33.wav<br />
* sound/ed/imp/alert_test34.wav<br />
* sound/ed/imp/alert_test39.wav<br />
* sound/ed/maggot/hiss3h2.ogg<br />
* sound/ed/pinky/pain_test1.wav .. sound/ed/pinky/pain_test7.wav<br />
* sound/ed/pinky3/death_test1.wav .. sound/ed/pinky3/death_test5.wav<br />
* sound/ed/pinky3/idle_test1.wav .. sound/ed/pinky3/idle_test4.wav<br />
* sound/ed/pinky3/sight3_test1.wav .. sound/ed/pinky3/sight3_test4.wav<br />
* sound/ed/pinky3/sight_test21.wav<br />
* sound/ed/pinky3/sight_test22.wav<br />
* sound/ed/pinky3/sight_test23.wav<br />
* sound/ed/player/player_land2.ogg<br />
* sound/ed/sfx/barrel1.ogg .. sound/ed/sfx/barrel5.ogg<br />
* sound/ed/sfx/wrench_impact1.ogg<br />
* sound/ed/sfx/wrench_impact2.ogg<br />
* sound/ed/spook/ohgodplease.ogg<br />
* sound/ed/spook/please.ogg<br />
* sound/ed/tick/chirp1.ogg .. sound/ed/tick/chirp6.ogg<br />
* sound/ed/tick/tick_death1.ogg .. sound/ed/tick/tick_death3.ogg<br />
* sound/ed/tick/tick_pain1.ogg .. sound/ed/tick/tick_pain4.ogg<br />
* <strike>sound/ed/tick/tick_walk1.wav .. sound/ed/tick/tick_walk6.wav</strike><br />
* sound/ed/trite/breath_hollow_deep4.ogg<br />
* sound/ed/trite/breath_hollow_raspy1.ogg<br />
* sound/ed/trite/breath_throaty6.ogg<br />
* sound/impact/ambient_impacts/emetal_01.wav .. sound/impact/ambient_impacts/emetal_05.wav<br />
* sound/impact/boxes/boxfall_18.ogg<br />
* sound/impact/crash/glasscrash_01.ogg .. sound/impact/crash/glasscrash_04.ogg<br />
* sound/impact/metal_doors/slam_01.ogg<br />
* sound/impact/metal_doors/slam_08_boomy.wav<br />
* sound/impact/metals/1shot_metalhit_01.ogg<br />
* sound/impact/metals/1shot_metalhit_03.ogg<br />
* sound/impact/metals/1shot_metalhit_06.ogg<br />
* sound/impact/shaky_metal_bangs/mbang_01.wav .. sound/impact/shaky_metal_bangs/mbang_05.wav<br />
* sound/impact/solid/impact_01.ogg<br />
* sound/impact/solid/impact_02.ogg<br />
* sound/impact/solid/impact_03.ogg<br />
* sound/impact/stairs/simpact_04.ogg<br />
* sound/impact/steel/clang_01.ogg<br />
* sound/impact/steel/clang_02.ogg<br />
* sound/impact/steel/clang_03.ogg<br />
* sound/impact/steel/clang_04.wav<br />
* sound/impact/steel/clang_05.ogg<br />
* sound/levels/caverns2/stone_movement_loop.wav<br />
* sound/levels/hell/thunderclap_01a.wav<br />
* sound/levels/hell/thunderclap_02a.wav<br />
* sound/levels/hell/thunderclap_03a.wav<br />
* sound/levels/hell/thunderclap_04a.wav<br />
* sound/machinery/loop_machinery_03.wav<br />
* sound/machinery/machines/loop_airpump_02.wav<br />
* sound/machinery/machines/loop_machinery_01.ogg<br />
* sound/machinery/machines/loop_machinery_02.ogg<br />
* sound/machinery/steamchuffs/steamchuff_01.ogg<br />
* sound/machinery/steamchuffs/steamchuff_02.ogg<br />
* sound/monsters/cacodemon/caco_chatter1.wav .. sound/monsters/cacodemon/caco_chatter6.wav<br />
* sound/monsters/cacodemon/pimpact_01.wav .. sound/monsters/cacodemon/pimpact_04.wav<br />
* sound/monsters/lost_soul/chatter_01.wav .. sound/monsters/lost_soul/chatter_03.wav<br />
* sound/monsters/maggot/distant_screams_01.ogg<br />
* sound/monsters/maggot/distant_screams_03.ogg<br />
* sound/monsters/maggot/idle_01.wav<br />
* sound/monsters/maggot/idle_02.wav<br />
* sound/monsters/maggot/idle_03.wav<br />
* sound/monsters/maggot/idle_04.wav<br />
* sound/monsters/trite/death21.wav<br />
* sound/monsters/trite/death22.wav<br />
* sound/monsters/trite/death23.wav<br />
* sound/monsters/trite/pain8.wav<br />
* sound/monsters/trite/pain9.wav<br />
* sound/monsters/trite/sight1.wav<br />
* sound/monsters/trite/sight3.wav<br />
* sound/monsters/trite/sight5.wav<br />
* sound/movers/_general_movement/m3_end.wav<br />
* sound/movers/_general_movement/m3_loop.wav<br />
* sound/movers/_general_movement/m3_start.wav<br />
* sound/sfx/voices/generic/brush01.ogg<br />
* sound/stress/1shot_creaking_02.wav<br />
* sound/weapons/casings/small_metal_02.wav<br />
* sound/weapons/explosions/explode_01.wav<br />
* sound/weapons/explosions/impexp_03.wav<br />
* sound/weapons/explosions/impexp_04.wav<br />
* sound/weapons/explosions/impexp_05.wav<br />
* sound/weapons/explosions/impexp_06.wav<br />
* sound/weapons/impacts/bullet_metal/metalimpact_04.wav<br />
* sound/xian/creepy/prayer/deliver_us.ogg<br />
* sound/xian/foley_sessions/coughs/cough_01.ogg .. sound/xian/foley_sessions/coughs/cough_05.ogg<br />
* <strike>sound/xian/foley_sessions/metals_small/lowtink_01.ogg .. sound/xian/foley_sessions/metals_small/lowtink_03.ogg</strike><br />
* sound/xian/roomtones2/dangerlow_01.wav<br />
* sound/xian/suspense/loop_suspense_07.wav<br />
* steam_01.wav<br />
* steelswing_01.wav<br />
* stone_movement_end.wav<br />
* teleport_machine_idle.wav<br />
* tincan.wav<br />
* vault_clock_ambient.wav<br />
* wind_01.wav<br />
* wind_02.wav<br />
<br />
==== Unused, but generating warnings ====<br />
<br />
These are probably automatically loaded, but never used and can be removed in the code:<br />
<br />
* player_sounds_doublevision.wav<br />
* player_sounds_guienter.wav<br />
* player_sounds_guiexit.wav<br />
* player_sounds_heartbeat.wav<br />
* player_sounds_heartbeat_dying.wav<br />
* player_sounds_hitflesh.wav<br />
* player_sounds_skipcinematic.wav<br />
* player_sounds_teleportexit.wav<br />
* player_sounds_teleportstart.wav<br />
* player_sounds_thud.wav<br />
<br />
=== AI ===<br />
<br />
* Zombie + animations<br />
* Joint 'Shoulders' not found for 'head_joint' on 'atdm_ai_undead_zombie_a...<br />
* models/md5/monsters/skeleton/skeleton.md5mesh<br />
<br />
=== Animations ===<br />
<br />
* models/md5/characters/npcs/zheads/z1idle.md5anim<br />
* models/md5/chars/af_pose.md5anim<br />
* models/md5/environments/hellchain.md5anim<br />
* models/md5/environments/swinglight_round.md5anim<br />
* models/md5/monsters/imp/initial.md5anim<br />
<br />
=== AF (Articulated Figures) ===<br />
<br />
* monster_demon_imp<br />
* monster_zombie_base<br />
* monster_zombie_bernie<br />
<br />
=== Models ===<br />
<br />
Static and moveable models, not counting meshes (for AI). These are missing and need to be redone:<br />
<br />
* models/gibs/brain_2xb.lwo<br />
* models/gibs/gib_left_arm.lwo<br />
* models/gibs/gib_left_leg.lwo<br />
* models/gibs/gib_right_foot.lwo<br />
* models/gibs/gib_torso.lwo<br />
* models/gibs/left_waist_pork.lwo<br />
* models/gibs/lup_leg_pork.lwo<br />
* models/mapobjects/caves/caverock1.ase<br />
* models/mapobjects/hell/mancroom/bars.lwo<br />
* models/mapobjects/lights/cagelight/cagelight.lwo<br />
* models/mapobjects/tables/bunkbed/mattress.lwo<br />
<br />
This one is a place holder for a quiver model, so we need a quiver instead this:<br />
<br />
* models/items/shells_ammo/shells_large.lwo<br />
<br />
We do miss some models altogether, and some models are modified versions of D3 meshes.<br />
They won't throw an error because they're included in the mod, but they can't be left in if TDM is going standalone:<br />
<br />
* pick-axe<br />
* wooden tray<br />
* several chain models<br />
* skull01 model<br />
* candle textures (and possibly mesh)<br />
* jar<br />
* noblewoman's legs<br />
* beggar's arms and legs<br />
* werebeast body<br />
* Sykes head and textures<br />
* head08 mesh and textures<br />
* head06 mesh and textures<br />
* head01 mesh and textures<br />
<br />
== See also ==<br />
<br />
* [[IdTech4 Open Source]]<br />
* [[Standalone Progress]]<br />
<br />
{{standalone}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Path_Nodes&diff=8627Path Nodes2009-07-15T17:23:58Z<p>Angua: /* How to use Path Nodes */</p>
<hr />
<div>''originally written by Springheel''<br />
<br />
For more information on pathfinding, see [[Pathfinding]].<br />
<br />
= What are Path Nodes? =<br />
<br />
Path entities (or path nodes) are the things that you use to make your AI move around the map. Placing path nodes can take a little getting used to; hopefully this article will help (I'm far from an expert, but here's what I've discovered so far).<br />
<br />
There are lots of different kinds of path nodes. It can sometimes help to think of them as "travel nodes" (nodes that AI will travel to) and "behaviour nodes" (nodes that tell AI how to behave at a certain point). <br />
<br />
Although path nodes have a directional arrow in the editor, it has no impact on most nodes. Rotating the node does add a corresponding "angle" property to the entity (matching the direction of the arrow). Certain nodes (path_anim and path_turn, for example) are affected by the "angle" property, but most will ignore it.<br />
<br />
= How to use Path Nodes =<br />
<br />
Path nodes are placed like any other entity (RMB and select "add entity", then scroll to "paths"). They show up as an orange box in the editor.<br />
<br />
Path nodes are useless if they are not linked to another entity (either an AI or another node). In order to link them, you use the "target" property. This tells the AI what pathnode they should go to (or act on) next. If you type "target" "path_corner_1" in your AI property list, then your AI will walk to "path_corner_1" when the map starts. Without a "target" property, your AI will not go anywhere. Once you add a "target" property to either your AI or another node, you should see an orange line connecting the two entities.<br />
<br />
Behaviour nodes activate behaviour in order. In other words, if you want an AI to reach a path_corner, then turn to face a direction, then wait for a time, then play an animation, you need to link the nodes in that order. <br />
<br />
path_corner ---> path_turn ----> path_wait ----> path_cycleanim -----> next path_corner<br />
<br />
It is also possible to target multiple nodes (using "target_1", "target_2" etc. spawn args). In this case, the AI will choose one of these nodes with equal probability. <br />
If the '''"chance"''' spawn arg (between 0 and 1) is set on a node, it defines the probability for the AI to choose this path node next when multiple path nodes are targetted.<br />
<br />
There are now two new spawnargs, '''"alert_idle_only"''' and '''"idle_only"''' that can be set on path nodes. The nodes are then only chosen when the AI is in that state. For example, if you set a path_corner as "idle_only", then the AI will no longer go to that path node when it has been alerted. This allows the mapper to set a complete set of alternate patrols and actions for AI who have been alerted (like sending them to guard important areas).<br />
<br />
Nodes that make the AI walk to a specified location (currently the only one that does this is the path_corner) can have an '''"move_to_position_tolerance"''' spawn arg, which defines how close the AI has to be to the destination point to determine the position as reached. Normally, the AI considers the position reached as soon as it is inside its bounding box (most of our humanoid AI are using aas32, so the point would need to be within 16 units from the AI's origin). This is not always accurate enough, for example when a path_corner is placed in front of a chair where the AI is supposed to sit down, making the AI place half of their back next to the chair.<br />
Setting the accuracy spawn arg will change the horizontal size of the bounding box used for checking. If the accuracy is set to negative values (default is -1), the standard bounding box will be used as before.<br />
<br />
This spawnarg is available for all entities and can also affect AIs moving towards levers or buttons.<br />
<br />
<br />
== path_corner ==<br />
Probably the most common path node, this is a "travel node". AI will walk from their current position to this node in as straight a line as possible. This node must be on the ground and in an area AI can reach. See [[Pathfinding]] for more information on how to help AI go from one node to another.<br />
<br />
To make AI patrol an area, each path_corner node can target the next one in sequence. If AI reach a node that does not target anything, they will stop there and no longer move without player interaction. It is possible for two path_nodes to target each other, which means the AI will walk from one to the other and back again endlessly.<br />
<br />
A single entity (path node or AI) can target more than one path_corner; D3 will randomly choose between the targetted nodes. Use the following syntax: ''(actually this syntax needs to be double checked)''<br />
<br />
target path_corner_1<br />
target_2 path_corner_2<br />
<br />
<br />
''(At the moment, targetting more than 2 path_corners from the same entity does not seem to work (possibly a DR bug).''<br />
<br />
In the example below, both A and B are path_corner nodes. On map start, the AI will walk to A, then turn and walk to B, then stop.<br />
<br />
[[image:pathfinding2.jpg]]<br />
<br />
<br />
'''Note that an AI will return to a path_corner ''(does it choose the nearest or most recent?)'' after a failed search. If you do not have at least one path_corner, the AI will stop wherever they are when their search is complete.'''<br />
<br />
== path_wait ==<br />
<br />
This is a behaviour node. It does not tell an AI to move anywhere. This node tells an AI to wait in an idle state for a given amount of time. Once that time is up, the AI will proceed to whatever the next target is (a path_wait with no target is pretty pointless). <br />
<br />
A path_wait node appears as a small orange box. It has a directional arrow, but that has no affect on which direction the AI faces in the first place. However, you can set the angle key on the path either by rotating the entity or by setting the key directly to make the AI turn and face this direction before starting to wait.<br />
<br />
A path_wait node should have a "wait" property, with the number of seconds the AI should wait there before proceeding. It can also have a "wait_max" property which will vary the repeat time. So for example...<br />
<br />
* wait 30<br />
* wait_max 40 <br />
<br />
...will cause the AI to wait between 30 to 40 seconds before proceeding. If wait_max is set to 0, the AI will always wait exactly the time specified in wait before proceeding. If you set wait to 0, the AI will wait between 0 seconds and the time specified in wait_max. Default values are 2 seconds for wait, and 0 seconds for wait_max, so the AI will always wait exactly 2 seconds.<br />
<br />
In the following example, A and B are path_corners, and the small orange box is a path_wait entity. On map start, the AI will walk to A and wait there for the required amount of time, then turn and proceeds to B.<br />
<br />
[[image:pathfinding3.jpg]]<br />
<br />
Note that it does not matter '''where''' the path_wait node is placed. The AI does not actually follow the orange lines (this is not really intuitive, I know). The example below would cause the exact same behaviour as the example above--in both cases the AI will walk directly from A to B.<br />
<br />
[[image:pathfinding4.jpg]]<br />
<br />
<br />
<br />
Another useful example for path_wait is that of the stationary guard who turns to look in different directions periodically. This can be schematically represented (arrows indicate target links) as:<br />
<br />
AI -> path_corner1 -> path_wait1 -> path_wait2 -> path_corner1<br />
<br />
Example properties for the path_wait are:<br />
wait: 5 (minimum time to wait on action)<br />
wait_max: 10 (maximum time to wait on action)<br />
angle: 0 ('''Important''': this property is essential for proper function even if the angle is 0)<br />
<br />
<br />
The AI walks to or stands at the path_corner. The next action is to do what is indicated by the first path_wait. In this example, it tells the AI to face a particular direction for a certain period of time. This then targets a second path_wait which has the AI face a different direction for a certain period of time. To complete the cycle, the second path_wait then targets the original path_corner. The path_corners are necessary because again, the path_wait doesn't contain pathing or location information. Without the path_corner, if the AI is caused to wander (e.g. becomes alerted), it might not return to the original standing spot, and instead will do the look angles right where it stands. The path_corner assures the AI returns to its original position.<br />
<br />
== path_turn == <br />
<br />
This behaviour node tells an AI to turn in place to face a chosen direction. It does not make the AI walk anywhere. This is the one node where the directional arrow does seem to matter--the AI turns to face the same direction as the arrow. Alternately, you can use the property "angle" and the values below:<br />
<br />
* 0 = East (X)<br />
* 90 = North (Y)<br />
* 180 = West (-X)<br />
* 270 = South (-Y)<br />
* 360 = East(X)<br />
<br />
(Actually, to be more accurate, rotating the entity automatically adds the "angle" property to the entity. If you just leave the arrow facing the way it is when you create the entity, there will be no "angle" property, and therefore the AI will not turn.)<br />
<br />
== path_anim ==<br />
<br />
This is a behaviour node that makes the AI play an animation, once. When that animation is done, it proceeds to the next target (if any). This could be used to make an AI walk over to a bookshelf and play a 'reaching out' animation, for example. <br />
<br />
The syntax proper syntax is:<br />
<br />
anim [animation name]<br />
<br />
You can see the list of animations names in the AI's def file. Do not use the name of the actual animation file. <br />
<br />
A path_anim can have only one animation, but it is possible for a single entity to target more than one path_anim. The AI will pick one of the path_anim nodes at random and play that animation.<br />
<br />
When you first create the path_anim entity, the directional arrow is meaningless. However, if you rotate the entity, the "angle" property is added to the entity and is updated based on which direction the arrow is pointing. That property indicates the direction the AI will face while playing the animation.<br />
<br />
'''Issues:''' Currently there are two problems with path_anim nodes. First, the animation seems to be played only on the torso channel (ie, it will not affect the AI's legs). Secondly, a random idle animation can interrupt the path_anim. Not only will this cut off the desired animation, but ''the AI will not proceed to the next target'' (pretty serious). ''[edit: this latter issue should be fixed now]''<br />
<br />
== path_sit ==<br />
<br />
This is a behaviour node that makes the AI sit down at its current location. See [[Sitting Behaviour for AI]] for more information.<br />
<br />
= Untested Nodes =<br />
<br />
I have not personally tested the following, so I'm just going by their editor descriptions. They may or may not work as described.<br />
<br />
<br />
== path_cycleanim ==<br />
<br />
The AI stays in place and loops the selected animation, either for a specified amount of time (using the 'wait' property) or until triggered. Syntax needed.<br />
<br />
== path_lookat ==<br />
<br />
This does not stop the AI, but they will turn their head and look somewhere specific as they walk to their next target. For the next ''wait'' seconds, turn head to look at the entity given by the ''focus'' spawnarg (defaults to looking at the path_lookat entity itself). This is useful if you want to make sure an AI is looking at a specific spot (or away from a certain spot) during their patrol.<br />
<br />
== path_waitfortrigger ==<br />
<br />
Waits at a given place until triggered, then proceeds to the next target. This is useful if you want some control over exactly where the AI is when the players first see it.<br />
<br />
== path_hide ==<br />
<br />
Deactivates and stops rendering the AI. Used to remove "ambient AI" from the map when they have served their purpose (ie, AI that are just there for flavour, like a messenger leaving the room and disappearing).<br />
<br />
== path_show ==<br />
<br />
Starts rendering the AI. I would assume this one would be linked to a path_waitfortrigger, to create AI that spawn when triggered. This could be used to create the effect that an AI just came through a doorway or around a corner.<br />
<br />
== path_attack ==<br />
<br />
Used to script AI attacking a particular enemy, for scripted sequences I guess. AI will continue on to the next path entity if it kills the enemy.<br />
<br />
Questions: How do you define who the AI attacks?<br />
<br />
[Fidcal]: Just found this - "Character will attack the character specified by 'enemy' key. Character will go to next path when enemy dies or when activated." Not tested.<br />
<br />
== path_interact ==<br />
<br />
This lets the AI interact with an entity (for example a button) in a similar way to frobbing. This will only work for buttons etc, not for inventory items and moveables. The AI will stop and look at the entiy while interacting, but not walk to it, so a path_corner next to the entity is required. AI will use normal doors and elevators without needing a path_interact (confirmation needed). However, this could be used to make AI turn on lightswitches, open mechanical doors, etc.<br />
<br />
Questions: what is the synatx for targetting the entity to interact with? How close does the AI need to be?<br />
<br />
{{tutorial-editing}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Path_Nodes&diff=8626Path Nodes2009-07-15T17:23:41Z<p>Angua: /* How to use Path Nodes */</p>
<hr />
<div>''originally written by Springheel''<br />
<br />
For more information on pathfinding, see [[Pathfinding]].<br />
<br />
= What are Path Nodes? =<br />
<br />
Path entities (or path nodes) are the things that you use to make your AI move around the map. Placing path nodes can take a little getting used to; hopefully this article will help (I'm far from an expert, but here's what I've discovered so far).<br />
<br />
There are lots of different kinds of path nodes. It can sometimes help to think of them as "travel nodes" (nodes that AI will travel to) and "behaviour nodes" (nodes that tell AI how to behave at a certain point). <br />
<br />
Although path nodes have a directional arrow in the editor, it has no impact on most nodes. Rotating the node does add a corresponding "angle" property to the entity (matching the direction of the arrow). Certain nodes (path_anim and path_turn, for example) are affected by the "angle" property, but most will ignore it.<br />
<br />
= How to use Path Nodes =<br />
<br />
Path nodes are placed like any other entity (RMB and select "add entity", then scroll to "paths"). They show up as an orange box in the editor.<br />
<br />
Path nodes are useless if they are not linked to another entity (either an AI or another node). In order to link them, you use the "target" property. This tells the AI what pathnode they should go to (or act on) next. If you type "target" "path_corner_1" in your AI property list, then your AI will walk to "path_corner_1" when the map starts. Without a "target" property, your AI will not go anywhere. Once you add a "target" property to either your AI or another node, you should see an orange line connecting the two entities.<br />
<br />
Behaviour nodes activate behaviour in order. In other words, if you want an AI to reach a path_corner, then turn to face a direction, then wait for a time, then play an animation, you need to link the nodes in that order. <br />
<br />
path_corner ---> path_turn ----> path_wait ----> path_cycleanim -----> next path_corner<br />
<br />
It is also possible to target multiple nodes (using "target_1", "target_2" etc. spawn args). In this case, the AI will choose one of these nodes with equal probability. <br />
If the '''"chance"''' spawn arg (between 0 and 1) is set on a node, it defines the probability for the AI to choose this path node next when multiple path nodes are targetted.<br />
<br />
There are now two new spawnargs, '''"alert_idle_only"''' and '''"idle_only"''' that can be set on path nodes. The nodes are then only chosen when the AI is in that state. For example, if you set a path_corner as "idle_only", then the AI will no longer go to that path node when it has been alerted. This allows the mapper to set a complete set of alternate patrols and actions for AI who have been alerted (like sending them to guard important areas).<br />
<br />
Nodes that make the AI walk to a specified location (currently the only one that does this is the path_corner) can have an '''"move_to_position_tolerance"''' spawn arg, which defines how close the AI has to be to the destination point to determine the position as reached. Normally, the AI considers the position reached as soon as it is inside its bounding box (most of our humanoid AI are using aas32, so the point would need to be within 16 units from the AI's origin). This is not always accurate enough, for example when a path_corner is placed in front of a chair where the AI is supposed to sit down, making the AI place half of their back next to the chair.<br />
Setting the accuracy spawn arg will change the horizontal size of the bounding box used for checking. If the accuracy is set to negative values (default is -1), the standard bounding box will be used as before.<br />
<br />
This spawnarg is available for all entities and can also affect AIs moving towards levers or buttons.<br />
<br />
<br />
<br />
<br />
== path_corner ==<br />
Probably the most common path node, this is a "travel node". AI will walk from their current position to this node in as straight a line as possible. This node must be on the ground and in an area AI can reach. See [[Pathfinding]] for more information on how to help AI go from one node to another.<br />
<br />
To make AI patrol an area, each path_corner node can target the next one in sequence. If AI reach a node that does not target anything, they will stop there and no longer move without player interaction. It is possible for two path_nodes to target each other, which means the AI will walk from one to the other and back again endlessly.<br />
<br />
A single entity (path node or AI) can target more than one path_corner; D3 will randomly choose between the targetted nodes. Use the following syntax: ''(actually this syntax needs to be double checked)''<br />
<br />
target path_corner_1<br />
target_2 path_corner_2<br />
<br />
<br />
''(At the moment, targetting more than 2 path_corners from the same entity does not seem to work (possibly a DR bug).''<br />
<br />
In the example below, both A and B are path_corner nodes. On map start, the AI will walk to A, then turn and walk to B, then stop.<br />
<br />
[[image:pathfinding2.jpg]]<br />
<br />
<br />
'''Note that an AI will return to a path_corner ''(does it choose the nearest or most recent?)'' after a failed search. If you do not have at least one path_corner, the AI will stop wherever they are when their search is complete.'''<br />
<br />
== path_wait ==<br />
<br />
This is a behaviour node. It does not tell an AI to move anywhere. This node tells an AI to wait in an idle state for a given amount of time. Once that time is up, the AI will proceed to whatever the next target is (a path_wait with no target is pretty pointless). <br />
<br />
A path_wait node appears as a small orange box. It has a directional arrow, but that has no affect on which direction the AI faces in the first place. However, you can set the angle key on the path either by rotating the entity or by setting the key directly to make the AI turn and face this direction before starting to wait.<br />
<br />
A path_wait node should have a "wait" property, with the number of seconds the AI should wait there before proceeding. It can also have a "wait_max" property which will vary the repeat time. So for example...<br />
<br />
* wait 30<br />
* wait_max 40 <br />
<br />
...will cause the AI to wait between 30 to 40 seconds before proceeding. If wait_max is set to 0, the AI will always wait exactly the time specified in wait before proceeding. If you set wait to 0, the AI will wait between 0 seconds and the time specified in wait_max. Default values are 2 seconds for wait, and 0 seconds for wait_max, so the AI will always wait exactly 2 seconds.<br />
<br />
In the following example, A and B are path_corners, and the small orange box is a path_wait entity. On map start, the AI will walk to A and wait there for the required amount of time, then turn and proceeds to B.<br />
<br />
[[image:pathfinding3.jpg]]<br />
<br />
Note that it does not matter '''where''' the path_wait node is placed. The AI does not actually follow the orange lines (this is not really intuitive, I know). The example below would cause the exact same behaviour as the example above--in both cases the AI will walk directly from A to B.<br />
<br />
[[image:pathfinding4.jpg]]<br />
<br />
<br />
<br />
Another useful example for path_wait is that of the stationary guard who turns to look in different directions periodically. This can be schematically represented (arrows indicate target links) as:<br />
<br />
AI -> path_corner1 -> path_wait1 -> path_wait2 -> path_corner1<br />
<br />
Example properties for the path_wait are:<br />
wait: 5 (minimum time to wait on action)<br />
wait_max: 10 (maximum time to wait on action)<br />
angle: 0 ('''Important''': this property is essential for proper function even if the angle is 0)<br />
<br />
<br />
The AI walks to or stands at the path_corner. The next action is to do what is indicated by the first path_wait. In this example, it tells the AI to face a particular direction for a certain period of time. This then targets a second path_wait which has the AI face a different direction for a certain period of time. To complete the cycle, the second path_wait then targets the original path_corner. The path_corners are necessary because again, the path_wait doesn't contain pathing or location information. Without the path_corner, if the AI is caused to wander (e.g. becomes alerted), it might not return to the original standing spot, and instead will do the look angles right where it stands. The path_corner assures the AI returns to its original position.<br />
<br />
== path_turn == <br />
<br />
This behaviour node tells an AI to turn in place to face a chosen direction. It does not make the AI walk anywhere. This is the one node where the directional arrow does seem to matter--the AI turns to face the same direction as the arrow. Alternately, you can use the property "angle" and the values below:<br />
<br />
* 0 = East (X)<br />
* 90 = North (Y)<br />
* 180 = West (-X)<br />
* 270 = South (-Y)<br />
* 360 = East(X)<br />
<br />
(Actually, to be more accurate, rotating the entity automatically adds the "angle" property to the entity. If you just leave the arrow facing the way it is when you create the entity, there will be no "angle" property, and therefore the AI will not turn.)<br />
<br />
== path_anim ==<br />
<br />
This is a behaviour node that makes the AI play an animation, once. When that animation is done, it proceeds to the next target (if any). This could be used to make an AI walk over to a bookshelf and play a 'reaching out' animation, for example. <br />
<br />
The syntax proper syntax is:<br />
<br />
anim [animation name]<br />
<br />
You can see the list of animations names in the AI's def file. Do not use the name of the actual animation file. <br />
<br />
A path_anim can have only one animation, but it is possible for a single entity to target more than one path_anim. The AI will pick one of the path_anim nodes at random and play that animation.<br />
<br />
When you first create the path_anim entity, the directional arrow is meaningless. However, if you rotate the entity, the "angle" property is added to the entity and is updated based on which direction the arrow is pointing. That property indicates the direction the AI will face while playing the animation.<br />
<br />
'''Issues:''' Currently there are two problems with path_anim nodes. First, the animation seems to be played only on the torso channel (ie, it will not affect the AI's legs). Secondly, a random idle animation can interrupt the path_anim. Not only will this cut off the desired animation, but ''the AI will not proceed to the next target'' (pretty serious). ''[edit: this latter issue should be fixed now]''<br />
<br />
== path_sit ==<br />
<br />
This is a behaviour node that makes the AI sit down at its current location. See [[Sitting Behaviour for AI]] for more information.<br />
<br />
= Untested Nodes =<br />
<br />
I have not personally tested the following, so I'm just going by their editor descriptions. They may or may not work as described.<br />
<br />
<br />
== path_cycleanim ==<br />
<br />
The AI stays in place and loops the selected animation, either for a specified amount of time (using the 'wait' property) or until triggered. Syntax needed.<br />
<br />
== path_lookat ==<br />
<br />
This does not stop the AI, but they will turn their head and look somewhere specific as they walk to their next target. For the next ''wait'' seconds, turn head to look at the entity given by the ''focus'' spawnarg (defaults to looking at the path_lookat entity itself). This is useful if you want to make sure an AI is looking at a specific spot (or away from a certain spot) during their patrol.<br />
<br />
== path_waitfortrigger ==<br />
<br />
Waits at a given place until triggered, then proceeds to the next target. This is useful if you want some control over exactly where the AI is when the players first see it.<br />
<br />
== path_hide ==<br />
<br />
Deactivates and stops rendering the AI. Used to remove "ambient AI" from the map when they have served their purpose (ie, AI that are just there for flavour, like a messenger leaving the room and disappearing).<br />
<br />
== path_show ==<br />
<br />
Starts rendering the AI. I would assume this one would be linked to a path_waitfortrigger, to create AI that spawn when triggered. This could be used to create the effect that an AI just came through a doorway or around a corner.<br />
<br />
== path_attack ==<br />
<br />
Used to script AI attacking a particular enemy, for scripted sequences I guess. AI will continue on to the next path entity if it kills the enemy.<br />
<br />
Questions: How do you define who the AI attacks?<br />
<br />
[Fidcal]: Just found this - "Character will attack the character specified by 'enemy' key. Character will go to next path when enemy dies or when activated." Not tested.<br />
<br />
== path_interact ==<br />
<br />
This lets the AI interact with an entity (for example a button) in a similar way to frobbing. This will only work for buttons etc, not for inventory items and moveables. The AI will stop and look at the entiy while interacting, but not walk to it, so a path_corner next to the entity is required. AI will use normal doors and elevators without needing a path_interact (confirmation needed). However, this could be used to make AI turn on lightswitches, open mechanical doors, etc.<br />
<br />
Questions: what is the synatx for targetting the entity to interact with? How close does the AI need to be?<br />
<br />
{{tutorial-editing}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Doors&diff=8625Doors2009-07-14T19:27:48Z<p>Angua: /* AI Door management */</p>
<hr />
<div>{{todo}}<br />
''Written by Fidcal'' ''edit Baddcog''<br />
<br />
==Quick Summary==<br />
<br />
Quick way to get an unlocked door in your map:<br />
<br />
* Create a door from the entity list<br />
* Use the "skin" spawnarg on the door to change its appearance. <br />
* Create a handle from the entity list<br />
* Add the ''door_handle'' property to the door and give it the name of the handle<br />
* To the door handle add the value frob_peer and use the name of the door.<br />
* To open clockwise, change the ''rotate'' property from <code>0 90 0</code> to <code>0 -90 0</code><br />
<br />
==Introduction==<br />
<br />
This tutorial explains how to put doors into your map using Dark Radiant, as well as adjust them and their properties.<br />
<br />
The rest of this tutorial assumes that you have a basic understanding of using DarkRadiant. If you haven't done so, please go read the [[Dark Radiant Must Know Basic Intro]] article first.<br />
<br />
Additionally:<br />
<br />
* Up, down, left, and right in Dark Radiant's ''top'' orthoview are regarded here as the standard map directions of North, South, East, and West where useful for clarity.<br />
* Where the term ''brush'' is used with a door it mostly also applies to a door made up of a group of brushes and/or patches.<br />
* Where the term ''door'' is used it often will also apply to any object you wish to rotate when frobbed, for instance an openable window, box lid, or even more exotic objects that the imaginative mapper might conceive like a signal, engine part, toy, or whatever. So long as it needs to turn or slide just a fixed amount when frobbed then return when frobbed again then the following applies.<br />
<br />
==Door types==<br />
<br />
All tangible objects in Dark Mod are ''entities'', having either a pre-made model shape or else brush/patch(es). So there are two ways to create a door in Dark Radiant: as a model door or a textured brush door (or a hybrid of the two).<br />
<br />
Models are ready made door objects but cannot within Dark Radiant (at the time of writing) be resized, rescaled, cropped or clipped whereas brushes are very flexible in that respect and can be worked into custom shapes for your map, including secret doors that blend into walls and other surfaces.<br />
<br />
Most of the current door models are found in two places along with the door handles.<br />
*Model Viewer: doors created from here will be static in the world and have no props other than material type.<br />
You can add any props to them to make them working doors. If nothing else it is a good place to view the different size and skin options for the doors.<br />
*Entity List: most of the door models can be found here. These doors have properties already assigned so they are ready to be used. Only one base door of each type is listed, create the size/hinge count door you want (2 hinge doors have a 'no hinge' skin). You can choose a skin for the door once it has been created in the editor with the "skin" spawnarg (use the model name of the door you want, taken from the model list, as its value). This is the easiest way to create a door. The same goes for door handles.<br />
<br />
Remember also that door functions may be applied to objects other than doors for instance to openable windows, drawbridges, gates, in fact anything that needs a partial rotation or slide when frobbed then return when frobbed again such as a signal device. Lockboxes and chests use similar properties.<br />
<br />
Door/handle prefabs seem to crash Doom3 when trying to reload a map so far now just create and link each door/handle. You can create one set and copy/paste them, but you need to take great care that all the name props are changed to match each clone. Otherwise you get handles that fly off with a distant door and handles that don't move.<br />
<br />
==Creating a Door==<br />
<br />
Put simply, to make a door you will be creating an 'entity with model' or 'entity with brush' or some variation thereof.<br />
<br />
===Creating a Model Door===<br />
<br />
There are several approaches to making a model door; the simplest is to create a door from the entity list; or create a door from the model viewer (good for static unusable prop doors).<br />
<br />
'''Entity List''':<br />
<br />
*Deselect everything in editor by hitting the Esc button<br />
*Right-click an ortho view and select Create Entity<br />
*Navigate to darkmod/movers/''atdm:door_...'', choose the door you want<br />
*Click Add<br />
*To change its appearance, add a "skin" spawnarg to the door, with the value being the model name of the door you want.<br />
<br />
You now have a workable door in your level.<br />
<br />
'''Model Viewer''':<br />
<br />
* Right click in the orthoview, select ''Create Model'' then <code>darkmod</code> and select a door.<br />
* Note that you can left drag the image in the ''Choose Model'' dialog to rotate it around.<br />
* Click [[Image:Button ok.png]] and you have a static door.<br />
* If you want to make it work (openable, frobbable) then:<br />
** Select the entity inspector,<br />
** Select the top classname line so it highlights<br />
** Select the func_static line in the input box ''below'' the properties window.<br />
** Edit <code>func_static</code> to <code>atdm:mover_door</code><br />
** Click {{check}} or press {{key-enter}}<br />
<br />
Alternatively you can do it the old way:<br />
<br />
* Create any temporary brush<br />
* Right click in orthoview and select <code>Create Entity</code> then <code>atdm:mover_door</code>.<br />
* Left lick the model name line in the entity inspector.<br />
* Below it on the ''Entity Inspector'' panel you should now see a button 'Choose Model'<br />
* Left click it, select a door model from the darkmod group.<br />
* Note that you can left drag the image in the ''Choose Model'' dialog to rotate it around.<br />
* The temporary brush was deleted.<br />
<br />
<br />
In all three instances, you now have a working door with default properties. <br />
<br />
Name your door by adding the prop (or modifing it) to name ''My_Door_1''. You can use any name that you feel is appropriate but all doors with handles attached ''must'' have their own specific name. Use the name My_Door_1 for your first attempt as it will be referenced when you get around to attaching handles (see below).<br />
<br />
To add a handle and other adjustments, see [[#Customising and Adjusting Door Properties]] below.<br />
<br />
===Creating a Textured Brush Door===<br />
<br />
'''Tip:''' If unsure of size then you might insert a temporary human AI first to get a sense of height.<br />
<br />
==== The simplest brush door: ====<br />
<br />
* Drag out a new brush to the size required, eg, a seven foot high door is 84" x 1.1 = about 90 units in Dark Radiant.<br />
* Give it a door texture from the texture browser (or wall texture for a secret door)<br />
* Right click in orthoview and select ''Create Entity'' then <code>atdm:mover_door</code><br />
* You now have a default door that rotates around its center.<br />
<br />
To move the rotation point to the door edge and other adjustments, see [[#Customising and Adjusting Door Properties]] below.<br />
<br />
==== Multi-brush doors: ====<br />
<br />
More complex multi-brush doors can be created using the [[Clipper]] tool, CSG, etc. - this is not covered in this tutorial. Then assign <code>atdm:mover_door</code> for that whole brush structure. Also you can collect various brushes positioned together in relation to one another as needed, select them all, then assign <code>atdm:mover_door</code> for the group. All the brushes will be children of the <code>atdm:mover_door</code> entity and will rotate and be frobbable, etc. as one unit, as one door. To add further brushes or even model shapes later see the section on [[#Adding handles and other items to doors]].<br />
<br />
Name your door by adding the prop (or modifing it) to name My_Door_1. You can use any name that you feel is appropriate but all doors with handles attached must have their own specific name. Use the name My_Door_1 for your first attempt as it will be referenced when you get around to attaching handles (see below). (repeated from above in case you didn't choose to create a model door)<br />
<br />
=== Double Doors ===<br />
Double doors are automatically recognised by the code when the doors are spawned. The prerequisite is that both doors are sharing/touching the same visportal. The spawnarg ''auto_setup_double_door'' (which defaults to "1") will take care of setting up the open/lock peer relationship between the two doors. The doors will open/close and lock/unlock along with each other as a result.<br />
<br />
What happens behind the scenes: the doors are adding each other to their internal open_peer and lock_peer list, which causes the double doors to perform the same action when frobbed or used.<br />
<br />
Note that ''auto_setup_double_door'' will not set the frob_peer relationship, i.e. each door will frob-highlight on its own without highlighting the other door. You'll need to add that spawnarg manually if you want to highlight the entire double door as one.<br />
<br />
==Customising and Adjusting Door Properties==<br />
<br />
Handles, lockplates, etc. can be added to doors and door properties can be adjusted for rotation, sliding, locking, and more.<br />
<br />
Some of the door models have hinge plates and lockboxes that are reskinnable with a good variety of skins.<br />
<br />
===Door handles and other door attachments===<br />
<br />
You can add handles and other items to doors such that they move correctly with the door whether rotating, sliding, or both and even if the door is not vertical such as a skylight or trapdoor.<br />
Handle models come in two types, ''single handles'' and ''double handles''. A single handle is one sided, this means the handle will be inside the door or outside the door, but not both. A double handle has a lever on the inside of the door and a handle on the outside of the door. Each has benefits.<br />
<br />
*'''''Single door handles''''':<br />
Single door handles can be used on a static door, a door that's just for show that no AI's or the player can use. In this case you should just create a door handle from the model viewer, it will be static and have no properties such as scripts. It is for looks only.<br />
<br />
Single handles can also be used inside AND outside of the same door to save on rendering. Unlike the double handles the handle on the inside of a portal won't render. The curved handle is only about 130 polys per side, but if you have a large area and 10 handles you can save 1,000 polys from being rendered. Everything counts when it comes to performance.<br />
I will call this ''multiple handles'', see more below.<br />
<br />
These can also be useful on brush doors created in the editor that may be very thin or very wide.<br />
<br />
*'''''Double door handles''''':<br />
These are models have have a handle inside and outside. The bonus is that they only use one entity. Maps are limited to about 4,000 entities but when you count lights, AI, sound speakers, ect... you can run out of entities quickly on a large map. If you plan on building a large map this is the way to go, even in a small map they have benefits, namely that you only have to attach one handle per door.<br />
<br />
Whether you decide to use a single handle or a double handle you must first follow the instructions below and attach one handle first. If you choose a double handle, follow the instructions below and you are done. If you choose a single handle type follow the instructions then also follow the ''multiple handle'' instructions for the second handle.<br />
<br />
Both single and double handle types can be found in two places. The model viewer which will create a static model good for show, you can manually add props to make them work OR you can look in the entity browser.<br />
Using a handle from the entity browser saves you a little bit of time as some props are already added, you just need to add the frob_peer names for the doors/handles and the door_handle name to the door.<br />
<br />
<br />
=== Adding a working model door handle===<br />
<br />
Quick summary:<br />
* Create a model or brush handle and make it an ''atdm:mover_door_handle'' entity.<br />
* Position it on your door. Use the opposite side from the door's multicolor X-Y-Z indicator (highlight the door to see it) if it's not obvious which side it goes on. <br />
* '''Bind''' the handle to the door<br />
* It should now be a working handle though may need adjustments of rotation etc. see later. <br />
<br />
<br />
Important: read preceding section on door handle types and performance issues first.<br />
<br />
This works with both a model door and a brush door:<br />
<br />
'''Rotation''':<br />
* By default the door handle entity rotates ''anti-clockwise'' (looked at from the front) then springs back. A ''double handle'' model is OK but two singles (see ''Multiple door handles'' below) need more care as only one is the functioning entity and the other is just attached to it. So anti-clockwise is fine for a door with its hinge on the left and the handle on the right - the handle will rotate down then spring back. If you put the functioning door handle on the other side you will have to change the default ''rotate'' property from -45 0 0 to 45 0 0. '''''Therefore it is easier to generally put this handle on the side of the door where the hinge is on the left and the non-functioning attachment handle on the other side.'''''<br />
*If your door only needs one handle, eg, a cupboard door, and from outside its hinge is on the right then you will need to change the ''rotate'' property of the handle as described above.<br />
<br />
'''''The functioning handle entity:'''''<br />
* Create an entity door handle (movers folder) or create a brush or model handle and assign it the entity ''atdm:mover_door_handle''.<br />
* Position it where you wish on your door.<br />
* '''Bind''' the handle to the door, by adding the "bind" spawnarg to the handle.<br />
<br />
You now have a working door handle with default properties.<br />
<br />
*'''Multiple door handles''':<br />
Now that you've got a handle attached to one side of the door it is time to add one to the other side (unless you used a double handle).<br />
* Create the new handle. The single handles come in left and right persuasions. A door needs a left facing handle on one side and a right facing handle on the other, so if you have already added the left handle create a right handle and line it up on the other side of the door.<br />
* Name this handle. I prefer to keep a naming convention for each door and it's respective handles, it makes things alot easier. The door is named '''My_Door_1''', the first handle is named '''My_Handle_1''' so name the second handle '''My_Handle_1_1'''. This will make it stay with the first handle in the entity list. This is important to keep organized. If you name it My_Handle_2 then when you get to another door named My_Door_2 you'll be confused.<br />
* Place and '''bind''' that handle to your door.<br />
<br />
You now have two single door handles on either side of the door that rotate together as if they were physically attached.<br />
<br />
'''To add a brush to a brush door''':<br />
* Select the new brush ''and'' the brush door all together; ''the entity '''must''' be selected '''last'''.''<br />
* Use {{menu|Edit|Reparent primitives}}. This ensures the parent entity adopts the new item(s).<br />
* If you have trouble selecting them in the orthoview because other brushes, etc. get selected then try in the camera view or as a last resort move them temporarily to an open area (but keep them in the same positions relative to each other.) Use {{key-shift}}+{{LMB}} on new item(s) then {{key-shift}}+{{LMB}} on main entity. Once they are all selected, use the {{menu|Edit|Reparent primitives}}.<br />
<br />
'''To add ''model'' static items''': knockers, hinges, static handles etc. to a ''Model Door'':<br />
* Select item<br />
* Right click in orthoview and select ''Create Entity'' then <code>entity func_static</code><br />
* Position it where you wish on your door.<br />
* To synchronize this with your particular door you need to add the property ''bind'' and the individual door name to the brush entity. To do this...<br />
** Select the model door.<br />
** In the entity inspector, select the ''name'' line<br />
** Select the bottom line in the input box ''below'' the properties window.<br />
** Copy the name<br />
** Deselect the door with {{key-esc}}<br />
** Select the brush entity<br />
** Add a property "bind" to it.<br />
** Change the value of the property by pasting in the door name<br />
** Click {{check}} or press {{key-enter}}<br />
<br />
'''To add ''brush'' static items''': knockers, hinges, static handles to a Model Door:<br />
* This method is not ideal but it seems to work OK.<br />
* Select the brush.<br />
* Right click in orthoview and select Create Entity then ''atdm:mover_door_handle''<br />
* Position it where you wish on your door.<br />
<br />
To synchronize this with your particular door you need to add the property ''door_handle'' on the door, and give as the value the name of the brush you just created.<br />
<br />
This brush turns like a handle. To stop it:<br />
<br />
* Adding ''rotate 0 0 0'' or disabling the handle script won't help.<br />
* Add a real working handle (as in the section above ''To add a working model door handle...'' and it must be added LAST.)<br />
<br />
If you don't want too see a real working handle added maybe try another tiny brush with the handle function and hide it inside the door?<br />
<br />
===Locking Doors===<br />
<br />
To lock a door check the ''show inherited properties'' in the entity inspector for a ''atdm:mover_door'' entity and you should see the ''locked'' property. Select it and in the input box below the properties you can change its value:<br />
<br />
* 0 = unlocked (default)<br />
* 1 = locked<br />
<br />
If locked it will require an entity that is associated with it to be able to act as a key to unlock it.<br />
<br />
Currently door handles on locked doors will rotate when frobbed, they will bounce back though and the door will stay locked until unlocked.<br />
<br />
===Keys===<br />
<br />
Assigning specific keys to specific doors is simple.<br />
<br />
* The key is just a func_static model or brush. All keys can be found in the Entity List, these keys have all required props, they just need to be named.<br />
<br />
If you create a key from the Model Viewer and want it to be useable<br />
* Make sure it has the properties:<br />
useable 1 [so it can be used by the door]<br />
frobable 1<br />
inv_name <unique name><br />
inv_category Keys<br />
inv_target player1<br />
inv_icon guis/assets/hud/inventory_icons/<icon name><br />
inv_stackable 0 or 1 where 1 can be used on all copies of the same key so they show as one entry in the inventory with a total.<br />
<br />
Add to the door the property <code>used_by</code> with the key as the value. Multiple keys can open the same door by using several <tt>used_by</tt> spawnargs:<br />
<br />
"used_by" "doorkey_1"<br />
"used_by1" "doorkey_2<br />
<br />
====Master Key for Testing====<br />
<br />
By default, ALL locks can be opened by any key named ''key_master''. Just create a key in your map, name it ''key_master'' and it becomes a master key for use while testing. Add inv_map_start 1 to it so it is in the player inventory at game start. Remember to delete it when your mission is finished.<br />
<br />
===Lockpicks===<br />
''by Baddcog''<br />
<br />
This section may need reviewing but is essentially correct<br />
<br />
To make a door ''lockpickable'' check the ''show inherited properties'' in the entity inspector for a ''atdm:mover_door'' entity and you should see the ''pickable'' property. Select it and in the input box below the properties you can change its value:<br />
<br />
* 0 = unpickable<br />
* 1 = pickable (default)<br />
<br />
If pickable then the door can be opened with a lockpick...<br />
<br />
There are four lock pick types.<br />
*'''S'''=snake<br />
*'''C'''=circular or round<br />
*'''B'''=bent<br />
*'''T'''=triangular<br />
<br />
A lock can be set with many pins and each pin needs a designated lockpick type (see above). Keep in mind that the lockpicking in The Darkmod is much more involved than in T2 or T3. You have more lockpicks, an infinite amount of pins and the player has to listen to sounds to know when a lock is pin is picked.<br />
<br />
This means that authors can be very evil and really frustrate the player, in which case their missions will probably not be played. So be nice to the player and don't waste your time. Use simple locks for the most part and save complicated locks for important sections and to build tension. Don't make the player use four lockpicks and have 20 pins to pick. In most cases 1 or 2 pins will suffice and it isn't necessary to include all four lockpicks with every mission.<br />
Also try to include a lock lever on lockboxes or chests, door handles will rotate as the pins are being picked. This gives the player visual clues to help with the picking.<br />
IMO this system is a huge leap foward for lockpicking but also has the ability to completely frustrate the player as stated above. Keep this in mind when designing your lockpick systems.<br />
<br />
These props go on the door itself, or the lid of a chest.<br />
*'''lock_pins''' 1327<br />
*'''lock_picktype''' bcst<br />
<br />
The lockpins property specifies how many pins each lockpicktype has.<br />
The lockpick_type property specifies how many times the player has to switch picks and which pick they have to use.<br />
<br />
So looking at the example above we have lockpick _type b(bent),c(circular),s(snake), and t(triangular). The player will have to use these lockpicks in this order. Once the bent lockpicks pins are open the player can advance to the circular pick and so forth.<br />
In the example above the lockpins specify in order which pick types have how many pins, so the b pick has 1 pin, the c pick has 3 pins, the s pick has 2 pins, the t pick has 7 pins.<br />
This is a VERY EVIL lock and the player will probably spend twenty minutes trying to pick it before they come knock down your door. This is exactly the type of lock you don't want to add to your map.<br />
<br />
*For most simple locks like a footlocker with some broadhead arrows a good lock type would be something like:<br />
<br />
lock_pins 2<br />
<br />
lock_picktype b<br />
<br />
*or:<br />
<br />
lock_pins 21<br />
<br />
lock_picktype ts<br />
<br />
*or:<br />
<br />
lock_pins 11<br />
<br />
lock_picktype cc<br />
<br />
*For more complicated locks you might want to use more picks, but not too many pins:<br />
<br />
lock_pins 11111<br />
<br />
lock_picktype tsbsc<br />
<br />
That's only one pin per type, but it is 5 types (a repeat on the snake pick) and could still take the player a bit of time to work through.<br />
<br />
lockpick_rotate - is placed on the door. It is the amount the visible rotating handle or pin rotates while picking.<br />
<br />
lockpick_translate - is placed on the door. It is the amount the visible handle or pin moves in a straigh line while picking.<br />
<br />
<br />
SEE ALSO SOUND SECTION FOR PINS.<br />
<br />
===Open, Partially Open, or Closed Door at Game Start===<br />
<br />
By default, doors are closed at game start. If you want a door to be already open or partially open then do the following.<br />
<br />
'''Note well: Create all doors in their ''closed'' position. Adjust as follows and they will automatically be at the open position when game starts.'''<br />
<br />
Already Open Rotating Door:<br />
* Select the door.<br />
* Select the entity inspector<br />
* Check ''show inherited properties''<br />
* Select the ''open'' property<br />
* Edit the value to 1 in the input box below and tick the check button<br />
* The door will now be fully open at game start.<br />
<br />
* If you want it only partly open:<br />
* Make sure its ''open'' property is set to 1 as above.<br />
* Right click the entity inspector and select ''add property'' <br />
* Click the + sign on the left of the top line where atdm:mover_door is listed to open the folder. (if atdm:mover_door is not listed then the entity was likely changed from eg, func_static. If so, save the map and reload to update the add property list)<br />
* scroll down, select ''start_rotate'' then click {{ok}}<br />
* This adds it to the property list.<br />
* Now select ''start_rotate'' in the property list.<br />
* Edit the bottom line of the input box ''below'' the properties window to the angle you want in the same form as described in the ''Rotate Direction and Open Angle'' section. So for example, to have a door that has a fully open default ''rotate'' value of 0 90 0 to start only half open you would give it a ''start_rotate'' value of 0 45 0. <br />
* In a similar way add the property ''first_frob_open".<br />
* Set it to 1 and a partly open door should then open fully on the first frob.<br />
* Set it to 0 and a partly open door should close on the first frob.<br />
<br />
<br />
Already Open Sliding Door:<br />
* Select the door.<br />
* Select the entity inspector<br />
* Check ''show inherited properties''<br />
* Select the ''open'' property<br />
* Edit the value to 1 in the input box below and click {{check}} or press {{key-enter}}<br />
* The door will now be fully open at game start.<br />
<br />
* If you want it only partly open:<br />
* Right click the entity inspector and select ''add property'' <br />
* Make sure its ''open'' property is set to 1<br />
* Click the + sign on the left of the top line where atdm:mover_door is listed to open the folder.<br />
* scroll down, select ''start_position'' then click OK. (if atdm:mover_door is not listed then the entity was likely changed from eg, func_static. If so, save the map and reload to update the add property list)<br />
* This adds it to the property list.<br />
* Now select ''start_position'' in the property list.<br />
* Edit the bottom line of the input box ''below'' the properties window to the position you want in the same form as described in the ''Sliding (Translation) Amount and Direction'' section. So for example, to have a door that has a fully open default ''translate'' value of 0 50 0 to start only half open you would give it a ''start_position'' value of 0 25 0.<br />
* In a similar way add the property ''first_frob_open".<br />
* Set it to 1 and a partly open door should then open fully on the first frob.<br />
* Set it to 0 and a partly open door should close on the first frob.<br />
<br />
===Rotation Centre, Pivot, Hinge point===<br />
<br />
The centre of rotation of a door is at the origin point of its entity and the door rotates with reference to the orientation of that origin point, not the world map. See ''Rotate Direction...'' for more about that. This section only deals with the ''position'' of the rotation centre in the door.<br />
<br />
Model Door Centre of Rotation:<br><br />
The centre of rotation of a model door cannot be changed within Dark Radiant. Because a model door rotates around the centre 'spine' of its back edge this will cause clipping (penetration into solid) as in this example (where the door is set to open to 89 degrees for clarity):<BR>[[Image:modelClipping.jpg]]<BR> So care is needed with placement. You will not normally position a door right next to a wall as in the example but against a shallow frame so clipping will barely be noticeable but either way it can be fixed. You can correct it by adding a translation (see ''Sliding (Translation) Directions'') value of half the door width in the direction of the door handle. This will gently move the door out as it rotates to clear any solid on that side as in this diagram:<br><br />
[[Image:DoorClip.jpg]]<br><br />
Half a door width will typically be about 2. Any 'attachments' such as door handles will still synchronize with the door movement whether the door is rotating, sliding, or both.<br />
<br />
<br />
Brush Door Centre of Rotation:<br><br />
The centre of rotation of a brush door ''can'' be changed. The default origin point of a brush is at its centre. Therefore a default rotating brush door will rotate around its centre when you first create it. So, mappers will commonly need to move that rotation point to a corner or even to some other offset position for example, for an openable window using the door function.<br />
<br />
Put simply, to move the rotation point of a brush door you need to move the entity origin relative to the brush(es.)<br />
<br />
Moving the entity origin (centre of rotation) relative to a brush door:<br />
<br />
* Select the brush door<br />
* Select ''Vertices mode'' (default shortcut key is {{key|name=V}} or button on top toolbar 'Select Vertices')<br />
* Drag the door's entity origin to the point where you want the door to rotate. This should be on the corner on the leading edge side (the side to where the door is opening.) to avoid clipping as in this diagram....<br />
[[Image:getCorner.jpg]]<br />
* You should now find that door rotates around that point.<br />
<br />
===Rotate Direction and Open Angle===<br />
<br />
By default, rotating doors open anti-clockwise (viewed from above) by 90 degrees from the start orientation. If you want to change this edit the ''rotate'' property in the entity inspector. Don't confuse this ''rotate'' property with the ''rotation'' property. In the entity inspector remember that to see the inherited rotate property you must check the box 'Show inherited properties'.<br />
<br />
The three values shown in the rotate property are degrees from the closed position around Y Z X ''entity origin axes'' (NOT absolute map axes) and so include any start ''rotation''. So the Z value is the axis vertical to the entity origin. If you tilt a model door over in Dark Radiant then its entity origin tilts too so the Z axis is tilted too (with respect to the world map vertical.) So with a normally opening model door if you lay it flat on its back it will open upwards and not rotate around on the floor. But a brush door must be treated differently...<br />
<br />
If you turn a brush door using the normal Dark Radiant rotate tool or the Transform Dialog (accessed via a shortcut key) then it only turns the brush ''relative'' to the entity. So, because the entity origin is by default aligned with the world map then ''in most cases'' you can regard a brush door as rotating with respect to the world map if you wish. But there will be a problem when you come to rotations that are not around the main Y Z X axes of the map, for instance a drawbridge that lowers down to the south east. You might think you can combine Y Z X values to get the result you want - and this can be done (for south east use 45 45 90) but it is a bit of a kludge and the drawbridge twists eccentrically as it lowers (though it arrives correctly!) So for such cases you need to turn the entity itself so its start position is facing south east. You can then just use 0 0 90 to lower the drawbridge perfectly because its Y axis is now pointing south east. To turn the entity you must type or paste the rotation values in directly because using the Dark Radiant rotation tool or Transform Dialog will only turn the brush not the entity. The values are rather lengthy (south east is 0.707107 0.707107 0 -0.707107 0.707107 0 0 0 1) so probably the easiest way is to create a temporary model door, turn it how you want, then select its rotation property. If you now deselect and re-select your brush door then that property will still be in the entity inspector input box and you need only click the check(tick) box to add it to the brush door. NOTE: ''neither the entity nor the brush will show as turned in Dark Radiant.'' Only the rotation property in the entity inspector will indicate the orientation. Instead of a rotated ''construction'', regard it as a rotation ''instruction'' for when the map is compiled.<br />
<br />
These are the rotate property fields. Remember they are all with reference to the door's entity ''not'' the world map. Since there is no absolute frame of reference I indicate them here as if the entity is aligned with the world map axes...<br />
<br />
* Positive Y = Open clockwise (Dark Radiant grid front view, looking north)<br />
* Negative Y = Open anti-clockwise (Dark Radiant grid front view, looking north)<br />
<br />
* Positive Z = Open anti-clockwise (Dark Radiant grid top view, looking down)<br />
* Negative Z = Open clockwise (Dark Radiant grid top view, looking down)<br />
<br />
* Positive X = Open anti-clockwise (Dark Radiant grid side view, looking west)<br />
* Negative X = Open clockwise (Dark Radiant grid side view, looking west)<br />
<br />
The values are in the range -179 to +180. Positive values give an anti-clockwise opening rotation (looking down from above) and negative values give a clockwise opening rotation. The value 180 is unique in that it continues in an anti-clockwise rotation when closing rather than returning clockwise so might be used if you can think of some object that might need such a motion when frobbed!<br />
<br />
Edit the rotate value by selecting it and using the input box at the bottom and clicking the check(tick) button. That will change the angle the door will open to. Note that the line with the original default of 0 90 0 will still be there but your new entry will be added on a separate line and that is the one that will work in the game. CAUTION: when adjusting later make sure you have your new line selected and not the original! If you do it will appear to change but your first setting will remain unaltered.<br />
<br />
Examples:<br />
* 0 90 0 = Opens anti-clockwise round the entity's 'vertical' to 90 degrees - typical default vertical door.<br />
* 0 0 90 = Lowers a drawbridge from the entity 'vertical' to horizontal.<br />
* 0 0 -45 = Opens clockwise by 45 degrees viewed from the east side. This might suit a skylight in a sloping roof.<br />
<br />
Combinations can be used and also combined with slide motions (see '''Sliding (Translation) Directions''') to produce exotic and useful motions. A door opening against an upward-sloping floor can thus have a ''lifting hinge'' and raise up slightly to clear the floor; a door can rotate towards you and slide back to one side very effectively.<br />
<br />
<br />
===Sliding (Translation) Amount and Direction===<br />
<br />
By default a Dark Mod door will rotate open. For most sliding doors you want to stop them rotating as well as make them slide. You cannot delete (remove) the ''rotate'' property - you have to set the ''rotate'' property to 0 0 0 to stop a door rotating (see ''Rotate Direction and Open Angle''.)<br />
<br />
Now edit the ''translate'' property value by selecting it (remember to have inherited properties box checked) and using the input box at the bottom and clicking the check(tick) button. That will change the distance the door will slide to. Note that the line with the original default of 0 0 0 will still be there but your new entry will be added on a separate line and that is the one that will work in the game. CAUTION: when adjusting later make sure you have your new line selected and not the original! If you do it will appear to change but your first setting will remain unaltered.<br />
<br />
Typically (but not always) you will want your sliding door to slide the width of the door. The three values in the translate property by default are 0 0 0 and are X Y Z ''absolute map'' values (irrespective of door orientation) where:<br />
<br />
* Positive X = Slide East (Right side of Dark Radiant grid in top view)<br />
* Negative X = Slide West (Left side of Dark Radiant grid in top view)<br />
* Positive Y = Slide North (top of Dark Radiant grid in top view)<br />
* Negative Y = Slide South (bottom of Dark Radiant grid in top view)<br />
* Positive Z = Slide Up (Top of Dark Radiant grid in side views)<br />
* Negative Z = Slide Down (Bottom of Dark Radiant grid in side views)<br />
<br />
So for a 50 unit wide door you want to slide fully to the east you would use 50 0 0 for the translate property values. A 100 unit portcullis sliding vertically up would need 0 0 100 to be fully raised.<br />
<br />
=== Doors Collision/Push Behaviour ===<br />
Doors are pushing all entities by default, except for the player. Doors will also stop moving when anything blocks their movement. However, this default behaviour can be changed by setting the according spawnargs:<br />
<br />
Set '''push_player''' to '''1''' to let the player be pushed by this door:<br />
"push_player" "1" // Push the player too (default is off)<br />
<br />
By default '''stop_when_blocked''' is set to 1 and if a door is blocked by an entity then even if the entity is removed afterwards, the door stays still. The next frob will close the door.<br />
<br />
Set '''stop_when_blocked''' to '''0''' to prevent the door from ending the opening sequence when anything blocks its way. It will still pause - but continue to open if the block is removed.<br />
"stop_when_blocked" "0" // door keeps moving after being blocked (default is off)<br />
With this setting, doors will still stop at blocking entities (the player, for instance), but will continue to move when the entity clears the way.<br />
<br />
There is another spawnarg which stops a door pushing a moveable. Apply this to the ''moveable'' not the door...<br />
<br />
"notPushable" "1"<br />
<br />
===Sounds and Sound Propagation through Doors and Doorways===<br />
<br />
Sound propagation relies on visportals. For details study [[Sound Propagation: Part 1]] and [[Sound Propagation: Part 2]] as well as [[Visportals]] This tutorial will just cover the relevant sound and sound propagation ''properties'' of doors. If you set the ''show inherited properties'' box in the entity inspector you can see them as described here.<br />
<br />
The sound of doors opening and closing is set in the snd_open and snd_close properties. You can silence them by setting the following properties as shown:<br />
<br />
''snd_open null''<br><br />
''snd_close null''<br />
<br />
Don't just use a dash - as it seems to cause a sound of its own.<br />
<br />
''snd_locked''<br><br />
The sound played when a player tries to open a locked door.<br />
<br />
''snd_unlock string''<br><br />
The sound played when a player unlocks a door.<br />
<br />
''loss_open''<br><br />
Drop in sound volume in dB when going through an open door. (default 1dB)<br />
<br />
''loss_closed''<br><br />
Drop in sound volume in dB when going through a closed door. (default 15dB) You would want to set this very high to block all sound with a thick door but very low for a barred gate for example.<br />
<br />
''loss_double_open''<br><br />
Drop in sound volume in dB when going through double doors when only one is open. (default 1dB)<br />
<br />
There are also various sound properties for lockpicking:<br><br />
''snd_lockpick_pin_1 through 14'' and ''snd_lockpick_pin_success''<br />
<br />
<br />
===Speed of Door Opening and Closing===<br />
<br />
Rotating Door Speed:<br><br />
At the time of writing, the time a rotating door takes to open or close is set in the ''move_time'' property whatever its maximum open angle. So with rotation set at say 150 degrees the door just opens faster than at say 80 degrees. This is likely to be changed to a constant angular velocity so check to see if there a new property added if the following no longer works. The problem is that if an interruptable (see Extra Notes) door is frobbed while in motion it stops; another frob will reverse the motion - so even if the door is only open a crack it will still take the full time to close and vice versa.<br />
<br />
To change the time a rotating door takes to open or close, make sure the door is selected then...<br />
<br />
* Right click the entity inspector and check ''show inherited properties''<br />
* Scroll down, select ''move_time''<br />
* Edit the second line of the input box ''below'' the properties window to the time you want.<br />
* The time is in seconds and decimal fractions can be used.<br />
* The default is 1 second and if set to this then the door opens and closes in one second whatever the maximum open angle, great or small.<br />
<br />
<br />
Sliding Door Speed:<br><br />
The speed of a sliding door is set in the ''translate_speed'' property. To add this, make sure the door is selected then...<br />
<br />
* Right click the entity inspector and check ''show inherited properties''<br />
* Scroll down, select ''translate_speed''<br />
* Edit the second line of the input box ''below'' the properties window to the speed you want.<br />
* The speed is in Dark Radiant grid units per second.<br />
* The default is 0 and if set to this then the door slides open in one second whatever the distance, great or small.<br />
* CAUTION: If you later change the door back to a rotating door then delete the ''translate_speed'' property or ensure it is set to 0 as (at the time of writing but this will be fixed) a bug makes rotating doors open and close instantly. (Note: you can still mix sliding with rotating but check - this bug might only be if ''translate'' is set to 0 0 0)<br />
<br />
===Visportals and Doors===<br />
<br />
A visportal face surrounded by solid at its edges and in contact with a door is closed when the door is closed and enabled when the door is open. In most cases you will place a visportal in contact with a working door unless you can see through the door (such as a true glass door or barred gate.) For full details see [[Visportals]].<br />
<br />
==Auto-Closing/Opening Doors==<br />
Doors that automatically close after being open for some time are easy to setup: Each frobmover entity supports these spawnargs:<br />
<br />
;"auto_close_time":Set this to something >= 0 to let the mover automatically close (again) after this time when being fully opened (measured in seconds). Defaults to -1, which means 'do not autoclose'. The event is also activated when the mover starts at the open position at map start.<br />
;"auto_open_time":"Set this to something >= 0 to let the mover automatically open (again) after this time when being fully closed (measured in seconds). Defaults to -1, which means 'do not autoopen'. The event is also activated when the mover starts at the closed position at map start.<br />
<br />
Old text:<br />
<br />
Note that auto-closing doors and AI closing doors behind them, is very much work in progress at the time of writing, so for now, this is another method that works. Check first if true AI closing of doors is working yet before bothering with this!<br />
<br />
I have one door that I particularly want the AI to close as there is a bit of frame lag inside if not. So I set this up and it works good as an auto-closing door - not as good as a true AI closing door as it will auto close when the player goes through as well but it does look very effective to see AI going through and closing the door behind them. Not tested exhaustively so I don't know if there could be any downside. Here's what to do....<br />
<br />
First a quick summary to make it more clear:<br />
<br />
'''''A trigger_relay is used both as a relay AND carries a stim. We put the trigger_relay with its stim in the path of the open door. The door has a response property. When it opens and contacts the stim its response is to send a signal back to the relay. The relay pauses then closes the door...'''''<br />
<br />
* First, optionally give your door a suitable name like autodoor1, whatever.<br />
* Copy that name to the clipboard.<br />
<br />
Next we need a relay with a delay:<br />
<br />
* Create entity > darkmod > trigger_relay<br />
<br />
* Place it roughly at the position the door will be at when open and to be on the safe side 3/4th of the way to the far end of the door (not the hinge end) to give max distance from the close door.<br />
<br />
* Add the property 'target' and paste in the door name you just copied.<br />
<br />
* Give the relay itself a name, eg, autoDoor_relay_1, and copy that name to the clipboard, you'll need that too in a bit.<br />
<br />
* Add the property delay and the value 3 - this is the delay in seconds before the door will close; 3 seems about right but 2 might be worth a try because to that 3 is added a random value between 0 to 0.5 seconds from the Time Interval we entered for the stim firings.<br />
<br />
* Add the property 'wait' and the value 3. This is the time before it can work again in seconds. If you set it too low then in theory the door might trigger again but in this situation I don't think it's possible. Too long, eg, one minute, and it won't work if the AI goes back through the door before then. If this value is -1 then the whole thing will only work ONCE so might be used for an AI who goes through once, closes it behind him, but you don't want it to be an autodoor thereafter.<br />
<br />
<br />
That's the relay, now we add a stim to it:<br />
<br />
* Still with the trigger relay selected, go to {{menu|Entity|Stim/Response}}<br />
<br />
* Custom stim tab.<br />
<br />
* Click Add stim type, select the new custom stim type you just made at the bottom of the list and type in eg, autoDoorStim at top right in the input box.<br />
<br />
* Click the stim tab and the little drop down arrow against the 'type' selector at bottom left and you should see your new custom stim name. Select it.<br />
<br />
* Select the new autoDoorStim in the list and on the right you need only type in the radius box 15.0 There is quite a lot of room for error. I had it working on 10 and also on 25. The value should be less than the distance to the closed door else it will trigger open! But no so small that the door might not reach it.<br />
<br />
* Select the check box for Time Interval and enter 500 (millisecs.) This is so it doesn't keep firing more frequently than is necessary. This stim will be firing all through your mission whether the door is used or not so if you had dozens of these then maybe it would affect performance. Too big a number and there may be a long delay before the door shuts - but it will be random depending on the next time the stim happens to fire. We'll control the delay we want more precisely later.<br />
<br />
* Click {{ok}} to confirm it.<br />
<br />
<br />
That's the stim set up, now for the response to it which is put on the door....<br />
<br />
* Select the doorm, then use {{menu|Entity|Stim/response}} and select the response tab.<br />
<br />
* Click the little drop down arrow against the 'type' selector at bottom left and you should see your new custom stim name. Select it.<br />
<br />
* Right click in the big ''Response Effects'' box on the bottom right of the panel.<br />
<br />
* Add New Effect and you should get a default 'Activate Response' response added to the list. Double click it.<br />
<br />
* In the Effect selector at the stop select 'Trigger'<br />
<br />
* in the Target box, paste in the name of the relay you copied or you can select it from the list at the little arrow.<br />
<br />
* Leave the Activator box empty.<br />
<br />
* Click {{apply}} and then {{ok}} on the main S & R panel bottom right.<br />
<br />
It should now work. No need to wait for an AI, just frob the door and watch it close itself. If not, check the position of the stim brush is close to where the door stops when open.<br />
<br />
==AI Door management==<br />
<br />
By default AI will open doors and close them behind them. Here are some spawnargs the mapper can use to modify that behaviour:<br />
<br />
;"ai_should_not_handle" :If set to 1, AI will not attempt to handle it and add it to the forbidden areas when closed (so that it doesn't try to path through). They might still walk through the door when it is open though. Useful if you have some special use door that you don't want the AI to operate.<br />
<br />
;"ai_should_not_close" :If set to 1, AI will not close the door behind them unless it obstructs them.<br />
<br />
<br />
To get AI to unlock/relock specific doors there are two methods currently:<br />
<br />
1. add the following spawnarg/value to the AI:<br />
<br />
;"can_unlock1" ''<doorname>''<br />
<br />
'''Do NOT use can_unlock_1.'''<br />
<br />
For additional doors on the same AI use ''can_unlock2 doorname'' etc.<br />
<br />
<br />
2. In the editor position an actual key that works for that door on the AI and also add to the key bind <AIname> and also bindToJoint LeftHips_Dummy (see other joints names elsewhere in wiki.) Currently, if the player pickpockets the key then the AI seeks an alternate route but otherwise does nothing (?) This may be upgraded in the future to better strategies.<br />
<br />
3. There is the possibility in the future of an additional method which would just use special attach spawnargs to make the above easier. The key would spawn at the correct position at game start. Watch this space.<br />
<br />
<br />
'''Door handling positions'''<br />
<br />
It is also possible to set custom door handling positions for the AI. This is especially useful when the standard routine that lets the AI choose their standing positions while opening and closing the door fails, leaving them circling around in front of the door helplessly.<br />
<br />
Place a atdm:door_handling_position entity where you want the AI to stand while opening/closing the door from this side.(it can be found in the movers folder in the entity chooser)<br />
<br />
On the door, you need to set the spawn arg "door_handle_position" "name_of_door_handling_position" You can also place a door handling position on each side of the door, the AI should automatically choose the right one. In this case, you need to set spawn args with "door_handle_position_1" etc and the corresponding names of the door handling position entities on the door.<br />
<br />
The door handling positions can also carry spawn args that define the behaviour of the AI, which are useful for example for doors that can only be openend or locked from one side:<br />
<br />
'''"ai_no_open"''' If set to true, the AI will not try to open the door from this side (but still walk through when the door is already open)<br />
<br />
'''"ai_no_close"''' If set to true, the AI will not attempt to close the door from this side<br />
<br />
'''"ai_no_unlock"''' If set true, the AI will not be able to unlock the door from this side, but still use it when it is not locked.<br />
<br />
'''"ai_no_lock"''' If this is set true, the AI will not lock the door from this side.<br />
<br />
==Doors as Triggers==<br />
<br />
''by Ishtvan & greebo''<br />
<br />
Doors (or any binary frob mover, buttons, levers, etc) now have the option to trigger their target on closing or opening. (For definition purposes, a button is defined as "closed" in the state when it starts out and "open" in the state you press it down to. I know that's a little non-intuitive, but it came from deriving from doors).<br />
<br />
New spawnargs on frob movers:<br />
;"trigger_on_open" :If set to 1, this binary mover will trigger its targets when it starts out completely closed and is opened.<br />
;"trigger_when_opened":If set to 1, this binary mover will trigger its targets when it is completely opened. Code defaults to 0.<br />
;"trigger_on_close":If set to 1, this binary mover will trigger its targets when it completely closes after being open.<br />
<br />
<br />
<br />
==Skins: A Wide Variety of Door Textures==<br />
<br />
This is to remind you that as with many Dark Mod models, there is a wide range of extras skins (textures) available for door models. There are now several basic door entities of different sizes so choose your size first. Then enter the spawnarg: skin with any temporary value. Now select it and click the skin button at the bottom of Dark Radiant's Entity Inspector and you will find a large of range of skin textures from which to select to give you a choice of appearances for your door.<br />
<br />
<br />
<br />
==Extra Notes==<br />
The property ''interruptable'' determines whether a door can be stopped by frobbing while it is opening or closing. So by frobbing then frobbing again, the player can open a door to any position, eg, slightly ajar to peek through.<br />
<br />
''func_darkmod_door'' is no longer used (just in case you come across it in the Dark Mod forums or wiki.) The Doom func_door is still available but for Dark Mod, but <code>atdm:mover_door</code> is the entity to use.<br />
<br />
{{tutorial-editing}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=AI_barks&diff=8557AI barks2009-06-26T11:13:45Z<p>Angua: </p>
<hr />
<div>AI use different barks when they have been alerted and when ramping down from an alert depending on the alert level and whether they have seen evidence of intruders before. Here is a little diagram:<br />
[[Image:Alert_barks.jpg]]<br />
<br />
{{ai}} {{sdk}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=AI_barks&diff=8556AI barks2009-06-26T11:12:19Z<p>Angua: </p>
<hr />
<div>AI use different barks when they have been alerted and when ramping down from an alert depending on the alert level and whether they have seen evidence of intruders before. Here is a little diagram:<br />
[[Image:Alert_barks.jpg]]</div>Anguahttps://wiki.thedarkmod.com/index.php?title=File:Alert_barks.jpg&diff=8555File:Alert barks.jpg2009-06-26T11:09:28Z<p>Angua: </p>
<hr />
<div></div>Anguahttps://wiki.thedarkmod.com/index.php?title=AI_barks&diff=8554AI barks2009-06-26T11:08:53Z<p>Angua: New page: AI use different barks when they have been alerted and when ramping down from an alert depending on the alert level and whether they have seen evidence of intruders before. Here is a littl...</p>
<hr />
<div>AI use different barks when they have been alerted and when ramping down from an alert depending on the alert level and whether they have seen evidence of intruders before. Here is a little diagram:</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Path_Nodes&diff=8521Path Nodes2009-06-22T10:08:55Z<p>Angua: /* How to use Path Nodes */</p>
<hr />
<div>''originally written by Springheel''<br />
<br />
For more information on pathfinding, see [[Pathfinding]].<br />
<br />
= What are Path Nodes? =<br />
<br />
Path entities (or path nodes) are the things that you use to make your AI move around the map. Placing path nodes can take a little getting used to; hopefully this article will help (I'm far from an expert, but here's what I've discovered so far).<br />
<br />
There are lots of different kinds of path nodes. It can sometimes help to think of them as "travel nodes" (nodes that AI will travel to) and "behaviour nodes" (nodes that tell AI how to behave at a certain point). <br />
<br />
Although path nodes have a directional arrow in the editor, it has no impact on most nodes. Rotating the node does add a corresponding "angle" property to the entity (matching the direction of the arrow). Certain nodes (path_anim and path_turn, for example) are affected by the "angle" property, but most will ignore it.<br />
<br />
= How to use Path Nodes =<br />
<br />
Path nodes are placed like any other entity (RMB and select "add entity", then scroll to "paths"). They show up as an orange box in the editor.<br />
<br />
Path nodes are useless if they are not linked to another entity (either an AI or another node). In order to link them, you use the "target" property. This tells the AI what pathnode they should go to (or act on) next. If you type "target" "path_corner_1" in your AI property list, then your AI will walk to "path_corner_1" when the map starts. Without a "target" property, your AI will not go anywhere. Once you add a "target" property to either your AI or another node, you should see an orange line connecting the two entities.<br />
<br />
Behaviour nodes activate behaviour in order. In other words, if you want an AI to reach a path_corner, then turn to face a direction, then wait for a time, then play an animation, you need to link the nodes in that order. <br />
<br />
path_corner ---> path_turn ----> path_wait ----> path_cycleanim -----> next path_corner<br />
<br />
It is also possible to target multiple nodes (using "target_1", "target_2" etc. spawn args). In this case, the AI will choose one of these nodes with equal probability. <br />
If the '''"chance"''' spawn arg (between 0 and 1) is set on a node, it defines the probability for the AI to choose this path node next when multiple path nodes are targetted.<br />
<br />
There are now two new spawnargs, '''"alert_idle_only"''' and '''"idle_only"''' that can be set on path nodes. The nodes are then only chosen when the AI is in that state. For example, if you set a path_corner as "idle_only", then the AI will no longer go to that path node when it has been alerted. This allows the mapper to set a complete set of alternate patrols and actions for AI who have been alerted (like sending them to guard important areas).<br />
<br />
Nodes that make the AI walk to a specified location (currently the only one that does this is the path_corner) can have an '''"accuracy"''' spawn arg, which defines how close the AI has to be to the destination point to determine the position as reached. Normally, the AI considers the position reached as soon as it is inside its bounding box (most of our humanoid AI are using aas32, so the point would need to be within 16 units from the AI's origin). This is not always accurate enough, for example when a path_corner is placed in front of a chair where the AI is supposed to sit down, making the AI place half of their back next to the chair.<br />
Setting the accuracy spawn arg will change the horizontal size of the bounding box used for checking. If the accuracy is set to negative values (default is -1), the standard bounding box will be used as before.<br />
<br />
<br />
<br />
== path_corner ==<br />
Probably the most common path node, this is a "travel node". AI will walk from their current position to this node in as straight a line as possible. This node must be on the ground and in an area AI can reach. See [[Pathfinding]] for more information on how to help AI go from one node to another.<br />
<br />
To make AI patrol an area, each path_corner node can target the next one in sequence. If AI reach a node that does not target anything, they will stop there and no longer move without player interaction. It is possible for two path_nodes to target each other, which means the AI will walk from one to the other and back again endlessly.<br />
<br />
A single entity (path node or AI) can target more than one path_corner; D3 will randomly choose between the targetted nodes. Use the following syntax: ''(actually this syntax needs to be double checked)''<br />
<br />
target path_corner_1<br />
target_2 path_corner_2<br />
<br />
<br />
''(At the moment, targetting more than 2 path_corners from the same entity does not seem to work (possibly a DR bug).''<br />
<br />
In the example below, both A and B are path_corner nodes. On map start, the AI will walk to A, then turn and walk to B, then stop.<br />
<br />
[[image:pathfinding2.jpg]]<br />
<br />
<br />
'''Note that an AI will return to a path_corner ''(does it choose the nearest or most recent?)'' after a failed search. If you do not have at least one path_corner, the AI will stop wherever they are when their search is complete.'''<br />
<br />
== path_wait ==<br />
<br />
This is a behaviour node. It does not tell an AI to move anywhere. This node tells an AI to wait in an idle state for a given amount of time. Once that time is up, the AI will proceed to whatever the next target is (a path_wait with no target is pretty pointless). <br />
<br />
A path_wait node appears as a small orange box. It has a directional arrow, but that has no affect on which direction the AI faces in the first place. However, you can set the angle key on the path either by rotating the entity or by setting the key directly to make the AI turn and face this direction before starting to wait.<br />
<br />
A path_wait node should have a "wait" property, with the number of seconds the AI should wait there before proceeding. It can also have a "wait_max" property which will vary the repeat time. So for example...<br />
<br />
* wait 30<br />
* wait_max 40 <br />
<br />
...will cause the AI to wait between 30 to 40 seconds before proceeding. If wait_max is set to 0, the AI will always wait exactly the time specified in wait before proceeding. If you set wait to 0, the AI will wait between 0 seconds and the time specified in wait_max. Default values are 2 seconds for wait, and 0 seconds for wait_max, so the AI will always wait exactly 2 seconds.<br />
<br />
In the following example, A and B are path_corners, and the small orange box is a path_wait entity. On map start, the AI will walk to A and wait there for the required amount of time, then turn and proceeds to B.<br />
<br />
[[image:pathfinding3.jpg]]<br />
<br />
Note that it does not matter '''where''' the path_wait node is placed. The AI does not actually follow the orange lines (this is not really intuitive, I know). The example below would cause the exact same behaviour as the example above--in both cases the AI will walk directly from A to B.<br />
<br />
[[image:pathfinding4.jpg]]<br />
<br />
<br />
<br />
Another useful example for path_wait is that of the stationary guard who turns to look in different directions periodically. This can be schematically represented (arrows indicate target links) as:<br />
<br />
AI -> path_corner1 -> path_wait1 -> path_wait2 -> path_corner1<br />
<br />
Example properties for the path_wait are:<br />
wait: 5 (minimum time to wait on action)<br />
wait_max: 10 (maximum time to wait on action)<br />
angle: 0 ('''Important''': this property is essential for proper function even if the angle is 0)<br />
<br />
<br />
The AI walks to or stands at the path_corner. The next action is to do what is indicated by the first path_wait. In this example, it tells the AI to face a particular direction for a certain period of time. This then targets a second path_wait which has the AI face a different direction for a certain period of time. To complete the cycle, the second path_wait then targets the original path_corner. The path_corners are necessary because again, the path_wait doesn't contain pathing or location information. Without the path_corner, if the AI is caused to wander (e.g. becomes alerted), it might not return to the original standing spot, and instead will do the look angles right where it stands. The path_corner assures the AI returns to its original position.<br />
<br />
== path_turn == <br />
<br />
This behaviour node tells an AI to turn in place to face a chosen direction. It does not make the AI walk anywhere. This is the one node where the directional arrow does seem to matter--the AI turns to face the same direction as the arrow. Alternately, you can use the property "angle" and the values below:<br />
<br />
* 0 = East (X)<br />
* 90 = North (Y)<br />
* 180 = West (-X)<br />
* 270 = South (-Y)<br />
* 360 = East(X)<br />
<br />
(Actually, to be more accurate, rotating the entity automatically adds the "angle" property to the entity. If you just leave the arrow facing the way it is when you create the entity, there will be no "angle" property, and therefore the AI will not turn.)<br />
<br />
== path_anim ==<br />
<br />
This is a behaviour node that makes the AI play an animation, once. When that animation is done, it proceeds to the next target (if any). This could be used to make an AI walk over to a bookshelf and play a 'reaching out' animation, for example. <br />
<br />
The syntax proper syntax is:<br />
<br />
anim [animation name]<br />
<br />
You can see the list of animations names in the AI's def file. Do not use the name of the actual animation file. <br />
<br />
A path_anim can have only one animation, but it is possible for a single entity to target more than one path_anim. The AI will pick one of the path_anim nodes at random and play that animation.<br />
<br />
When you first create the path_anim entity, the directional arrow is meaningless. However, if you rotate the entity, the "angle" property is added to the entity and is updated based on which direction the arrow is pointing. That property indicates the direction the AI will face while playing the animation.<br />
<br />
'''Issues:''' Currently there are two problems with path_anim nodes. First, the animation seems to be played only on the torso channel (ie, it will not affect the AI's legs). Secondly, a random idle animation can interrupt the path_anim. Not only will this cut off the desired animation, but ''the AI will not proceed to the next target'' (pretty serious). ''[edit: this latter issue should be fixed now]''<br />
<br />
== path_sit ==<br />
<br />
This is a behaviour node that makes the AI sit down at its current location. See [[Sitting Behaviour for AI]] for more information.<br />
<br />
= Untested Nodes =<br />
<br />
I have not personally tested the following, so I'm just going by their editor descriptions. They may or may not work as described.<br />
<br />
<br />
== path_cycleanim ==<br />
<br />
The AI stays in place and loops the selected animation, either for a specified amount of time (using the 'wait' property) or until triggered. Syntax needed.<br />
<br />
== path_lookat ==<br />
<br />
This does not stop the AI, but they will turn their head and look somewhere specific as they walk to their next target. For the next ''wait'' seconds, turn head to look at the entity given by the ''focus'' spawnarg (defaults to looking at the path_lookat entity itself). This is useful if you want to make sure an AI is looking at a specific spot (or away from a certain spot) during their patrol.<br />
<br />
== path_waitfortrigger ==<br />
<br />
Waits at a given place until triggered, then proceeds to the next target. This is useful if you want some control over exactly where the AI is when the players first see it.<br />
<br />
== path_hide ==<br />
<br />
Deactivates and stops rendering the AI. Used to remove "ambient AI" from the map when they have served their purpose (ie, AI that are just there for flavour, like a messenger leaving the room and disappearing).<br />
<br />
== path_show ==<br />
<br />
Starts rendering the AI. I would assume this one would be linked to a path_waitfortrigger, to create AI that spawn when triggered. This could be used to create the effect that an AI just came through a doorway or around a corner.<br />
<br />
== path_attack ==<br />
<br />
Used to script AI attacking a particular enemy, for scripted sequences I guess. AI will continue on to the next path entity if it kills the enemy.<br />
<br />
Questions: How do you define who the AI attacks?<br />
<br />
[Fidcal]: Just found this - "Character will attack the character specified by 'enemy' key. Character will go to next path when enemy dies or when activated." Not tested.<br />
<br />
== path_interact ==<br />
<br />
This lets the AI interact with an entity (for example a button) in a similar way to frobbing. This will only work for buttons etc, not for inventory items and moveables. The AI will stop and look at the entiy while interacting, but not walk to it, so a path_corner next to the entity is required. AI will use normal doors and elevators without needing a path_interact (confirmation needed). However, this could be used to make AI turn on lightswitches, open mechanical doors, etc.<br />
<br />
Questions: what is the synatx for targetting the entity to interact with? How close does the AI need to be?<br />
<br />
{{tutorial-editing}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Path_Nodes&diff=8520Path Nodes2009-06-22T09:29:21Z<p>Angua: /* How to use Path Nodes */</p>
<hr />
<div>''originally written by Springheel''<br />
<br />
For more information on pathfinding, see [[Pathfinding]].<br />
<br />
= What are Path Nodes? =<br />
<br />
Path entities (or path nodes) are the things that you use to make your AI move around the map. Placing path nodes can take a little getting used to; hopefully this article will help (I'm far from an expert, but here's what I've discovered so far).<br />
<br />
There are lots of different kinds of path nodes. It can sometimes help to think of them as "travel nodes" (nodes that AI will travel to) and "behaviour nodes" (nodes that tell AI how to behave at a certain point). <br />
<br />
Although path nodes have a directional arrow in the editor, it has no impact on most nodes. Rotating the node does add a corresponding "angle" property to the entity (matching the direction of the arrow). Certain nodes (path_anim and path_turn, for example) are affected by the "angle" property, but most will ignore it.<br />
<br />
= How to use Path Nodes =<br />
<br />
Path nodes are placed like any other entity (RMB and select "add entity", then scroll to "paths"). They show up as an orange box in the editor.<br />
<br />
Path nodes are useless if they are not linked to another entity (either an AI or another node). In order to link them, you use the "target" property. This tells the AI what pathnode they should go to (or act on) next. If you type "target" "path_corner_1" in your AI property list, then your AI will walk to "path_corner_1" when the map starts. Without a "target" property, your AI will not go anywhere. Once you add a "target" property to either your AI or another node, you should see an orange line connecting the two entities.<br />
<br />
Behaviour nodes activate behaviour in order. In other words, if you want an AI to reach a path_corner, then turn to face a direction, then wait for a time, then play an animation, you need to link the nodes in that order. <br />
<br />
path_corner ---> path_turn ----> path_wait ----> path_cycleanim -----> next path_corner<br />
<br />
It is also possible to target multiple nodes (using "target_1", "target_2" etc. spawn args). In this case, the AI will choose one of these nodes with equal probability. <br />
If the '''"chance"''' spawn arg (between 0 and 1) is set on a node, it defines the probability for the AI to choose this path node next when multiple path nodes are targetted.<br />
<br />
There are now two new spawnargs, '''"alert_idle_only"''' and '''"idle_only"''' that can be set on path nodes. The nodes are then only chosen when the AI is in that state. For example, if you set a path_corner as "idle_only", then the AI will no longer go to that path node when it has been alerted. This allows the mapper to set a complete set of alternate patrols and actions for AI who have been alerted (like sending them to guard important areas).<br />
<br />
Nodes that make the AI walk to a specified location (currently the only one that does this is the path_corner) can have an '''"accuracy"''' spawn arg, which defines how close the AI has to be to the destination point to determine the position as "reached". Normally, the AI considers the position reached as soon as it is inside its bounding box.<br />
<br />
<br />
<br />
== path_corner ==<br />
Probably the most common path node, this is a "travel node". AI will walk from their current position to this node in as straight a line as possible. This node must be on the ground and in an area AI can reach. See [[Pathfinding]] for more information on how to help AI go from one node to another.<br />
<br />
To make AI patrol an area, each path_corner node can target the next one in sequence. If AI reach a node that does not target anything, they will stop there and no longer move without player interaction. It is possible for two path_nodes to target each other, which means the AI will walk from one to the other and back again endlessly.<br />
<br />
A single entity (path node or AI) can target more than one path_corner; D3 will randomly choose between the targetted nodes. Use the following syntax: ''(actually this syntax needs to be double checked)''<br />
<br />
target path_corner_1<br />
target_2 path_corner_2<br />
<br />
<br />
''(At the moment, targetting more than 2 path_corners from the same entity does not seem to work (possibly a DR bug).''<br />
<br />
In the example below, both A and B are path_corner nodes. On map start, the AI will walk to A, then turn and walk to B, then stop.<br />
<br />
[[image:pathfinding2.jpg]]<br />
<br />
<br />
'''Note that an AI will return to a path_corner ''(does it choose the nearest or most recent?)'' after a failed search. If you do not have at least one path_corner, the AI will stop wherever they are when their search is complete.'''<br />
<br />
== path_wait ==<br />
<br />
This is a behaviour node. It does not tell an AI to move anywhere. This node tells an AI to wait in an idle state for a given amount of time. Once that time is up, the AI will proceed to whatever the next target is (a path_wait with no target is pretty pointless). <br />
<br />
A path_wait node appears as a small orange box. It has a directional arrow, but that has no affect on which direction the AI faces in the first place. However, you can set the angle key on the path either by rotating the entity or by setting the key directly to make the AI turn and face this direction before starting to wait.<br />
<br />
A path_wait node should have a "wait" property, with the number of seconds the AI should wait there before proceeding. It can also have a "wait_max" property which will vary the repeat time. So for example...<br />
<br />
* wait 30<br />
* wait_max 40 <br />
<br />
...will cause the AI to wait between 30 to 40 seconds before proceeding. If wait_max is set to 0, the AI will always wait exactly the time specified in wait before proceeding. If you set wait to 0, the AI will wait between 0 seconds and the time specified in wait_max. Default values are 2 seconds for wait, and 0 seconds for wait_max, so the AI will always wait exactly 2 seconds.<br />
<br />
In the following example, A and B are path_corners, and the small orange box is a path_wait entity. On map start, the AI will walk to A and wait there for the required amount of time, then turn and proceeds to B.<br />
<br />
[[image:pathfinding3.jpg]]<br />
<br />
Note that it does not matter '''where''' the path_wait node is placed. The AI does not actually follow the orange lines (this is not really intuitive, I know). The example below would cause the exact same behaviour as the example above--in both cases the AI will walk directly from A to B.<br />
<br />
[[image:pathfinding4.jpg]]<br />
<br />
<br />
<br />
Another useful example for path_wait is that of the stationary guard who turns to look in different directions periodically. This can be schematically represented (arrows indicate target links) as:<br />
<br />
AI -> path_corner1 -> path_wait1 -> path_wait2 -> path_corner1<br />
<br />
Example properties for the path_wait are:<br />
wait: 5 (minimum time to wait on action)<br />
wait_max: 10 (maximum time to wait on action)<br />
angle: 0 ('''Important''': this property is essential for proper function even if the angle is 0)<br />
<br />
<br />
The AI walks to or stands at the path_corner. The next action is to do what is indicated by the first path_wait. In this example, it tells the AI to face a particular direction for a certain period of time. This then targets a second path_wait which has the AI face a different direction for a certain period of time. To complete the cycle, the second path_wait then targets the original path_corner. The path_corners are necessary because again, the path_wait doesn't contain pathing or location information. Without the path_corner, if the AI is caused to wander (e.g. becomes alerted), it might not return to the original standing spot, and instead will do the look angles right where it stands. The path_corner assures the AI returns to its original position.<br />
<br />
== path_turn == <br />
<br />
This behaviour node tells an AI to turn in place to face a chosen direction. It does not make the AI walk anywhere. This is the one node where the directional arrow does seem to matter--the AI turns to face the same direction as the arrow. Alternately, you can use the property "angle" and the values below:<br />
<br />
* 0 = East (X)<br />
* 90 = North (Y)<br />
* 180 = West (-X)<br />
* 270 = South (-Y)<br />
* 360 = East(X)<br />
<br />
(Actually, to be more accurate, rotating the entity automatically adds the "angle" property to the entity. If you just leave the arrow facing the way it is when you create the entity, there will be no "angle" property, and therefore the AI will not turn.)<br />
<br />
== path_anim ==<br />
<br />
This is a behaviour node that makes the AI play an animation, once. When that animation is done, it proceeds to the next target (if any). This could be used to make an AI walk over to a bookshelf and play a 'reaching out' animation, for example. <br />
<br />
The syntax proper syntax is:<br />
<br />
anim [animation name]<br />
<br />
You can see the list of animations names in the AI's def file. Do not use the name of the actual animation file. <br />
<br />
A path_anim can have only one animation, but it is possible for a single entity to target more than one path_anim. The AI will pick one of the path_anim nodes at random and play that animation.<br />
<br />
When you first create the path_anim entity, the directional arrow is meaningless. However, if you rotate the entity, the "angle" property is added to the entity and is updated based on which direction the arrow is pointing. That property indicates the direction the AI will face while playing the animation.<br />
<br />
'''Issues:''' Currently there are two problems with path_anim nodes. First, the animation seems to be played only on the torso channel (ie, it will not affect the AI's legs). Secondly, a random idle animation can interrupt the path_anim. Not only will this cut off the desired animation, but ''the AI will not proceed to the next target'' (pretty serious). ''[edit: this latter issue should be fixed now]''<br />
<br />
== path_sit ==<br />
<br />
This is a behaviour node that makes the AI sit down at its current location. See [[Sitting Behaviour for AI]] for more information.<br />
<br />
= Untested Nodes =<br />
<br />
I have not personally tested the following, so I'm just going by their editor descriptions. They may or may not work as described.<br />
<br />
<br />
== path_cycleanim ==<br />
<br />
The AI stays in place and loops the selected animation, either for a specified amount of time (using the 'wait' property) or until triggered. Syntax needed.<br />
<br />
== path_lookat ==<br />
<br />
This does not stop the AI, but they will turn their head and look somewhere specific as they walk to their next target. For the next ''wait'' seconds, turn head to look at the entity given by the ''focus'' spawnarg (defaults to looking at the path_lookat entity itself). This is useful if you want to make sure an AI is looking at a specific spot (or away from a certain spot) during their patrol.<br />
<br />
== path_waitfortrigger ==<br />
<br />
Waits at a given place until triggered, then proceeds to the next target. This is useful if you want some control over exactly where the AI is when the players first see it.<br />
<br />
== path_hide ==<br />
<br />
Deactivates and stops rendering the AI. Used to remove "ambient AI" from the map when they have served their purpose (ie, AI that are just there for flavour, like a messenger leaving the room and disappearing).<br />
<br />
== path_show ==<br />
<br />
Starts rendering the AI. I would assume this one would be linked to a path_waitfortrigger, to create AI that spawn when triggered. This could be used to create the effect that an AI just came through a doorway or around a corner.<br />
<br />
== path_attack ==<br />
<br />
Used to script AI attacking a particular enemy, for scripted sequences I guess. AI will continue on to the next path entity if it kills the enemy.<br />
<br />
Questions: How do you define who the AI attacks?<br />
<br />
[Fidcal]: Just found this - "Character will attack the character specified by 'enemy' key. Character will go to next path when enemy dies or when activated." Not tested.<br />
<br />
== path_interact ==<br />
<br />
This lets the AI interact with an entity (for example a button) in a similar way to frobbing. This will only work for buttons etc, not for inventory items and moveables. The AI will stop and look at the entiy while interacting, but not walk to it, so a path_corner next to the entity is required. AI will use normal doors and elevators without needing a path_interact (confirmation needed). However, this could be used to make AI turn on lightswitches, open mechanical doors, etc.<br />
<br />
Questions: what is the synatx for targetting the entity to interact with? How close does the AI need to be?<br />
<br />
{{tutorial-editing}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Path_Nodes&diff=8519Path Nodes2009-06-22T09:24:23Z<p>Angua: /* path_wait */</p>
<hr />
<div>''originally written by Springheel''<br />
<br />
For more information on pathfinding, see [[Pathfinding]].<br />
<br />
= What are Path Nodes? =<br />
<br />
Path entities (or path nodes) are the things that you use to make your AI move around the map. Placing path nodes can take a little getting used to; hopefully this article will help (I'm far from an expert, but here's what I've discovered so far).<br />
<br />
There are lots of different kinds of path nodes. It can sometimes help to think of them as "travel nodes" (nodes that AI will travel to) and "behaviour nodes" (nodes that tell AI how to behave at a certain point). <br />
<br />
Although path nodes have a directional arrow in the editor, it has no impact on most nodes. Rotating the node does add a corresponding "angle" property to the entity (matching the direction of the arrow). Certain nodes (path_anim and path_turn, for example) are affected by the "angle" property, but most will ignore it.<br />
<br />
= How to use Path Nodes =<br />
<br />
Path nodes are placed like any other entity (RMB and select "add entity", then scroll to "paths"). They show up as an orange box in the editor.<br />
<br />
Path nodes are useless if they are not linked to another entity (either an AI or another node). In order to link them, you use the "target" property. This tells the AI what pathnode they should go to (or act on) next. If you type "target" "path_corner_1" in your AI property list, then your AI will walk to "path_corner_1" when the map starts. Without a "target" property, your AI will not go anywhere. Once you add a "target" property to either your AI or another node, you should see an orange line connecting the two entities.<br />
<br />
Behaviour nodes activate behaviour in order. In other words, if you want an AI to reach a path_corner, then turn to face a direction, then wait for a time, then play an animation, you need to link the nodes in that order. <br />
<br />
path_corner ---> path_turn ----> path_wait ----> path_cycleanim -----> next path_corner<br />
<br />
It is also possible to target multiple nodes (using "target_1", "target_2" etc. spawn args). In this case, the AI will choose one of these nodes with equal probability. <br />
If the '''"chance"''' spawn arg (between 0 and 1) is set on a node, it defines the probability for the AI to choose this path node next when multiple path nodes are targetted.<br />
<br />
There are now two new spawnargs, '''"alert_idle_only"''' and '''"idle_only"''' that can be set on path nodes. The nodes are then only chosen when the AI is in that state. For example, if you set a path_corner as "idle_only", then the AI will no longer go to that path node when it has been alerted. This allows the mapper to set a complete set of alternate patrols and actions for AI who have been alerted (like sending them to guard important areas).<br />
<br />
<br />
<br />
== path_corner ==<br />
Probably the most common path node, this is a "travel node". AI will walk from their current position to this node in as straight a line as possible. This node must be on the ground and in an area AI can reach. See [[Pathfinding]] for more information on how to help AI go from one node to another.<br />
<br />
To make AI patrol an area, each path_corner node can target the next one in sequence. If AI reach a node that does not target anything, they will stop there and no longer move without player interaction. It is possible for two path_nodes to target each other, which means the AI will walk from one to the other and back again endlessly.<br />
<br />
A single entity (path node or AI) can target more than one path_corner; D3 will randomly choose between the targetted nodes. Use the following syntax: ''(actually this syntax needs to be double checked)''<br />
<br />
target path_corner_1<br />
target_2 path_corner_2<br />
<br />
<br />
''(At the moment, targetting more than 2 path_corners from the same entity does not seem to work (possibly a DR bug).''<br />
<br />
In the example below, both A and B are path_corner nodes. On map start, the AI will walk to A, then turn and walk to B, then stop.<br />
<br />
[[image:pathfinding2.jpg]]<br />
<br />
<br />
'''Note that an AI will return to a path_corner ''(does it choose the nearest or most recent?)'' after a failed search. If you do not have at least one path_corner, the AI will stop wherever they are when their search is complete.'''<br />
<br />
== path_wait ==<br />
<br />
This is a behaviour node. It does not tell an AI to move anywhere. This node tells an AI to wait in an idle state for a given amount of time. Once that time is up, the AI will proceed to whatever the next target is (a path_wait with no target is pretty pointless). <br />
<br />
A path_wait node appears as a small orange box. It has a directional arrow, but that has no affect on which direction the AI faces in the first place. However, you can set the angle key on the path either by rotating the entity or by setting the key directly to make the AI turn and face this direction before starting to wait.<br />
<br />
A path_wait node should have a "wait" property, with the number of seconds the AI should wait there before proceeding. It can also have a "wait_max" property which will vary the repeat time. So for example...<br />
<br />
* wait 30<br />
* wait_max 40 <br />
<br />
...will cause the AI to wait between 30 to 40 seconds before proceeding. If wait_max is set to 0, the AI will always wait exactly the time specified in wait before proceeding. If you set wait to 0, the AI will wait between 0 seconds and the time specified in wait_max. Default values are 2 seconds for wait, and 0 seconds for wait_max, so the AI will always wait exactly 2 seconds.<br />
<br />
In the following example, A and B are path_corners, and the small orange box is a path_wait entity. On map start, the AI will walk to A and wait there for the required amount of time, then turn and proceeds to B.<br />
<br />
[[image:pathfinding3.jpg]]<br />
<br />
Note that it does not matter '''where''' the path_wait node is placed. The AI does not actually follow the orange lines (this is not really intuitive, I know). The example below would cause the exact same behaviour as the example above--in both cases the AI will walk directly from A to B.<br />
<br />
[[image:pathfinding4.jpg]]<br />
<br />
<br />
<br />
Another useful example for path_wait is that of the stationary guard who turns to look in different directions periodically. This can be schematically represented (arrows indicate target links) as:<br />
<br />
AI -> path_corner1 -> path_wait1 -> path_wait2 -> path_corner1<br />
<br />
Example properties for the path_wait are:<br />
wait: 5 (minimum time to wait on action)<br />
wait_max: 10 (maximum time to wait on action)<br />
angle: 0 ('''Important''': this property is essential for proper function even if the angle is 0)<br />
<br />
<br />
The AI walks to or stands at the path_corner. The next action is to do what is indicated by the first path_wait. In this example, it tells the AI to face a particular direction for a certain period of time. This then targets a second path_wait which has the AI face a different direction for a certain period of time. To complete the cycle, the second path_wait then targets the original path_corner. The path_corners are necessary because again, the path_wait doesn't contain pathing or location information. Without the path_corner, if the AI is caused to wander (e.g. becomes alerted), it might not return to the original standing spot, and instead will do the look angles right where it stands. The path_corner assures the AI returns to its original position.<br />
<br />
== path_turn == <br />
<br />
This behaviour node tells an AI to turn in place to face a chosen direction. It does not make the AI walk anywhere. This is the one node where the directional arrow does seem to matter--the AI turns to face the same direction as the arrow. Alternately, you can use the property "angle" and the values below:<br />
<br />
* 0 = East (X)<br />
* 90 = North (Y)<br />
* 180 = West (-X)<br />
* 270 = South (-Y)<br />
* 360 = East(X)<br />
<br />
(Actually, to be more accurate, rotating the entity automatically adds the "angle" property to the entity. If you just leave the arrow facing the way it is when you create the entity, there will be no "angle" property, and therefore the AI will not turn.)<br />
<br />
== path_anim ==<br />
<br />
This is a behaviour node that makes the AI play an animation, once. When that animation is done, it proceeds to the next target (if any). This could be used to make an AI walk over to a bookshelf and play a 'reaching out' animation, for example. <br />
<br />
The syntax proper syntax is:<br />
<br />
anim [animation name]<br />
<br />
You can see the list of animations names in the AI's def file. Do not use the name of the actual animation file. <br />
<br />
A path_anim can have only one animation, but it is possible for a single entity to target more than one path_anim. The AI will pick one of the path_anim nodes at random and play that animation.<br />
<br />
When you first create the path_anim entity, the directional arrow is meaningless. However, if you rotate the entity, the "angle" property is added to the entity and is updated based on which direction the arrow is pointing. That property indicates the direction the AI will face while playing the animation.<br />
<br />
'''Issues:''' Currently there are two problems with path_anim nodes. First, the animation seems to be played only on the torso channel (ie, it will not affect the AI's legs). Secondly, a random idle animation can interrupt the path_anim. Not only will this cut off the desired animation, but ''the AI will not proceed to the next target'' (pretty serious). ''[edit: this latter issue should be fixed now]''<br />
<br />
== path_sit ==<br />
<br />
This is a behaviour node that makes the AI sit down at its current location. See [[Sitting Behaviour for AI]] for more information.<br />
<br />
= Untested Nodes =<br />
<br />
I have not personally tested the following, so I'm just going by their editor descriptions. They may or may not work as described.<br />
<br />
<br />
== path_cycleanim ==<br />
<br />
The AI stays in place and loops the selected animation, either for a specified amount of time (using the 'wait' property) or until triggered. Syntax needed.<br />
<br />
== path_lookat ==<br />
<br />
This does not stop the AI, but they will turn their head and look somewhere specific as they walk to their next target. For the next ''wait'' seconds, turn head to look at the entity given by the ''focus'' spawnarg (defaults to looking at the path_lookat entity itself). This is useful if you want to make sure an AI is looking at a specific spot (or away from a certain spot) during their patrol.<br />
<br />
== path_waitfortrigger ==<br />
<br />
Waits at a given place until triggered, then proceeds to the next target. This is useful if you want some control over exactly where the AI is when the players first see it.<br />
<br />
== path_hide ==<br />
<br />
Deactivates and stops rendering the AI. Used to remove "ambient AI" from the map when they have served their purpose (ie, AI that are just there for flavour, like a messenger leaving the room and disappearing).<br />
<br />
== path_show ==<br />
<br />
Starts rendering the AI. I would assume this one would be linked to a path_waitfortrigger, to create AI that spawn when triggered. This could be used to create the effect that an AI just came through a doorway or around a corner.<br />
<br />
== path_attack ==<br />
<br />
Used to script AI attacking a particular enemy, for scripted sequences I guess. AI will continue on to the next path entity if it kills the enemy.<br />
<br />
Questions: How do you define who the AI attacks?<br />
<br />
[Fidcal]: Just found this - "Character will attack the character specified by 'enemy' key. Character will go to next path when enemy dies or when activated." Not tested.<br />
<br />
== path_interact ==<br />
<br />
This lets the AI interact with an entity (for example a button) in a similar way to frobbing. This will only work for buttons etc, not for inventory items and moveables. The AI will stop and look at the entiy while interacting, but not walk to it, so a path_corner next to the entity is required. AI will use normal doors and elevators without needing a path_interact (confirmation needed). However, this could be used to make AI turn on lightswitches, open mechanical doors, etc.<br />
<br />
Questions: what is the synatx for targetting the entity to interact with? How close does the AI need to be?<br />
<br />
{{tutorial-editing}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Path_Nodes&diff=8518Path Nodes2009-06-22T09:23:48Z<p>Angua: /* path_wait */</p>
<hr />
<div>''originally written by Springheel''<br />
<br />
For more information on pathfinding, see [[Pathfinding]].<br />
<br />
= What are Path Nodes? =<br />
<br />
Path entities (or path nodes) are the things that you use to make your AI move around the map. Placing path nodes can take a little getting used to; hopefully this article will help (I'm far from an expert, but here's what I've discovered so far).<br />
<br />
There are lots of different kinds of path nodes. It can sometimes help to think of them as "travel nodes" (nodes that AI will travel to) and "behaviour nodes" (nodes that tell AI how to behave at a certain point). <br />
<br />
Although path nodes have a directional arrow in the editor, it has no impact on most nodes. Rotating the node does add a corresponding "angle" property to the entity (matching the direction of the arrow). Certain nodes (path_anim and path_turn, for example) are affected by the "angle" property, but most will ignore it.<br />
<br />
= How to use Path Nodes =<br />
<br />
Path nodes are placed like any other entity (RMB and select "add entity", then scroll to "paths"). They show up as an orange box in the editor.<br />
<br />
Path nodes are useless if they are not linked to another entity (either an AI or another node). In order to link them, you use the "target" property. This tells the AI what pathnode they should go to (or act on) next. If you type "target" "path_corner_1" in your AI property list, then your AI will walk to "path_corner_1" when the map starts. Without a "target" property, your AI will not go anywhere. Once you add a "target" property to either your AI or another node, you should see an orange line connecting the two entities.<br />
<br />
Behaviour nodes activate behaviour in order. In other words, if you want an AI to reach a path_corner, then turn to face a direction, then wait for a time, then play an animation, you need to link the nodes in that order. <br />
<br />
path_corner ---> path_turn ----> path_wait ----> path_cycleanim -----> next path_corner<br />
<br />
It is also possible to target multiple nodes (using "target_1", "target_2" etc. spawn args). In this case, the AI will choose one of these nodes with equal probability. <br />
If the '''"chance"''' spawn arg (between 0 and 1) is set on a node, it defines the probability for the AI to choose this path node next when multiple path nodes are targetted.<br />
<br />
There are now two new spawnargs, '''"alert_idle_only"''' and '''"idle_only"''' that can be set on path nodes. The nodes are then only chosen when the AI is in that state. For example, if you set a path_corner as "idle_only", then the AI will no longer go to that path node when it has been alerted. This allows the mapper to set a complete set of alternate patrols and actions for AI who have been alerted (like sending them to guard important areas).<br />
<br />
<br />
<br />
== path_corner ==<br />
Probably the most common path node, this is a "travel node". AI will walk from their current position to this node in as straight a line as possible. This node must be on the ground and in an area AI can reach. See [[Pathfinding]] for more information on how to help AI go from one node to another.<br />
<br />
To make AI patrol an area, each path_corner node can target the next one in sequence. If AI reach a node that does not target anything, they will stop there and no longer move without player interaction. It is possible for two path_nodes to target each other, which means the AI will walk from one to the other and back again endlessly.<br />
<br />
A single entity (path node or AI) can target more than one path_corner; D3 will randomly choose between the targetted nodes. Use the following syntax: ''(actually this syntax needs to be double checked)''<br />
<br />
target path_corner_1<br />
target_2 path_corner_2<br />
<br />
<br />
''(At the moment, targetting more than 2 path_corners from the same entity does not seem to work (possibly a DR bug).''<br />
<br />
In the example below, both A and B are path_corner nodes. On map start, the AI will walk to A, then turn and walk to B, then stop.<br />
<br />
[[image:pathfinding2.jpg]]<br />
<br />
<br />
'''Note that an AI will return to a path_corner ''(does it choose the nearest or most recent?)'' after a failed search. If you do not have at least one path_corner, the AI will stop wherever they are when their search is complete.'''<br />
<br />
== path_wait ==<br />
<br />
This is a behaviour node. It does not tell an AI to move anywhere. This node tells an AI to wait in an idle state for a given amount of time. Once that time is up, the AI will proceed to whatever the next target is (a path_wait with no target is pretty pointless). <br />
<br />
A path_wait node appears as a small orange box. It has a directional arrow, but that has no affect on which direction the AI faces in the first place. You can set the angle key on the path either by rotating the entity or by setting the key directly to make the AI turn and face this direction before starting to wait.<br />
<br />
A path_wait node should have a "wait" property, with the number of seconds the AI should wait there before proceeding. It can also have a "wait_max" property which will vary the repeat time. So for example...<br />
<br />
* wait 30<br />
* wait_max 40 <br />
<br />
...will cause the AI to wait between 30 to 40 seconds before proceeding. If wait_max is set to 0, the AI will always wait exactly the time specified in wait before proceeding. If you set wait to 0, the AI will wait between 0 seconds and the time specified in wait_max. Default values are 2 seconds for wait, and 0 seconds for wait_max, so the AI will always wait exactly 2 seconds.<br />
<br />
In the following example, A and B are path_corners, and the small orange box is a path_wait entity. On map start, the AI will walk to A and wait there for the required amount of time, then turn and proceeds to B.<br />
<br />
[[image:pathfinding3.jpg]]<br />
<br />
Note that it does not matter '''where''' the path_wait node is placed. The AI does not actually follow the orange lines (this is not really intuitive, I know). The example below would cause the exact same behaviour as the example above--in both cases the AI will walk directly from A to B.<br />
<br />
[[image:pathfinding4.jpg]]<br />
<br />
<br />
<br />
Another useful example for path_wait is that of the stationary guard who turns to look in different directions periodically. This can be schematically represented (arrows indicate target links) as:<br />
<br />
AI -> path_corner1 -> path_wait1 -> path_wait2 -> path_corner1<br />
<br />
Example properties for the path_wait are:<br />
wait: 5 (minimum time to wait on action)<br />
wait_max: 10 (maximum time to wait on action)<br />
angle: 0 ('''Important''': this property is essential for proper function even if the angle is 0)<br />
<br />
<br />
The AI walks to or stands at the path_corner. The next action is to do what is indicated by the first path_wait. In this example, it tells the AI to face a particular direction for a certain period of time. This then targets a second path_wait which has the AI face a different direction for a certain period of time. To complete the cycle, the second path_wait then targets the original path_corner. The path_corners are necessary because again, the path_wait doesn't contain pathing or location information. Without the path_corner, if the AI is caused to wander (e.g. becomes alerted), it might not return to the original standing spot, and instead will do the look angles right where it stands. The path_corner assures the AI returns to its original position.<br />
<br />
== path_turn == <br />
<br />
This behaviour node tells an AI to turn in place to face a chosen direction. It does not make the AI walk anywhere. This is the one node where the directional arrow does seem to matter--the AI turns to face the same direction as the arrow. Alternately, you can use the property "angle" and the values below:<br />
<br />
* 0 = East (X)<br />
* 90 = North (Y)<br />
* 180 = West (-X)<br />
* 270 = South (-Y)<br />
* 360 = East(X)<br />
<br />
(Actually, to be more accurate, rotating the entity automatically adds the "angle" property to the entity. If you just leave the arrow facing the way it is when you create the entity, there will be no "angle" property, and therefore the AI will not turn.)<br />
<br />
== path_anim ==<br />
<br />
This is a behaviour node that makes the AI play an animation, once. When that animation is done, it proceeds to the next target (if any). This could be used to make an AI walk over to a bookshelf and play a 'reaching out' animation, for example. <br />
<br />
The syntax proper syntax is:<br />
<br />
anim [animation name]<br />
<br />
You can see the list of animations names in the AI's def file. Do not use the name of the actual animation file. <br />
<br />
A path_anim can have only one animation, but it is possible for a single entity to target more than one path_anim. The AI will pick one of the path_anim nodes at random and play that animation.<br />
<br />
When you first create the path_anim entity, the directional arrow is meaningless. However, if you rotate the entity, the "angle" property is added to the entity and is updated based on which direction the arrow is pointing. That property indicates the direction the AI will face while playing the animation.<br />
<br />
'''Issues:''' Currently there are two problems with path_anim nodes. First, the animation seems to be played only on the torso channel (ie, it will not affect the AI's legs). Secondly, a random idle animation can interrupt the path_anim. Not only will this cut off the desired animation, but ''the AI will not proceed to the next target'' (pretty serious). ''[edit: this latter issue should be fixed now]''<br />
<br />
== path_sit ==<br />
<br />
This is a behaviour node that makes the AI sit down at its current location. See [[Sitting Behaviour for AI]] for more information.<br />
<br />
= Untested Nodes =<br />
<br />
I have not personally tested the following, so I'm just going by their editor descriptions. They may or may not work as described.<br />
<br />
<br />
== path_cycleanim ==<br />
<br />
The AI stays in place and loops the selected animation, either for a specified amount of time (using the 'wait' property) or until triggered. Syntax needed.<br />
<br />
== path_lookat ==<br />
<br />
This does not stop the AI, but they will turn their head and look somewhere specific as they walk to their next target. For the next ''wait'' seconds, turn head to look at the entity given by the ''focus'' spawnarg (defaults to looking at the path_lookat entity itself). This is useful if you want to make sure an AI is looking at a specific spot (or away from a certain spot) during their patrol.<br />
<br />
== path_waitfortrigger ==<br />
<br />
Waits at a given place until triggered, then proceeds to the next target. This is useful if you want some control over exactly where the AI is when the players first see it.<br />
<br />
== path_hide ==<br />
<br />
Deactivates and stops rendering the AI. Used to remove "ambient AI" from the map when they have served their purpose (ie, AI that are just there for flavour, like a messenger leaving the room and disappearing).<br />
<br />
== path_show ==<br />
<br />
Starts rendering the AI. I would assume this one would be linked to a path_waitfortrigger, to create AI that spawn when triggered. This could be used to create the effect that an AI just came through a doorway or around a corner.<br />
<br />
== path_attack ==<br />
<br />
Used to script AI attacking a particular enemy, for scripted sequences I guess. AI will continue on to the next path entity if it kills the enemy.<br />
<br />
Questions: How do you define who the AI attacks?<br />
<br />
[Fidcal]: Just found this - "Character will attack the character specified by 'enemy' key. Character will go to next path when enemy dies or when activated." Not tested.<br />
<br />
== path_interact ==<br />
<br />
This lets the AI interact with an entity (for example a button) in a similar way to frobbing. This will only work for buttons etc, not for inventory items and moveables. The AI will stop and look at the entiy while interacting, but not walk to it, so a path_corner next to the entity is required. AI will use normal doors and elevators without needing a path_interact (confirmation needed). However, this could be used to make AI turn on lightswitches, open mechanical doors, etc.<br />
<br />
Questions: what is the synatx for targetting the entity to interact with? How close does the AI need to be?<br />
<br />
{{tutorial-editing}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Path_Nodes&diff=8517Path Nodes2009-06-22T09:21:10Z<p>Angua: /* path_wait */</p>
<hr />
<div>''originally written by Springheel''<br />
<br />
For more information on pathfinding, see [[Pathfinding]].<br />
<br />
= What are Path Nodes? =<br />
<br />
Path entities (or path nodes) are the things that you use to make your AI move around the map. Placing path nodes can take a little getting used to; hopefully this article will help (I'm far from an expert, but here's what I've discovered so far).<br />
<br />
There are lots of different kinds of path nodes. It can sometimes help to think of them as "travel nodes" (nodes that AI will travel to) and "behaviour nodes" (nodes that tell AI how to behave at a certain point). <br />
<br />
Although path nodes have a directional arrow in the editor, it has no impact on most nodes. Rotating the node does add a corresponding "angle" property to the entity (matching the direction of the arrow). Certain nodes (path_anim and path_turn, for example) are affected by the "angle" property, but most will ignore it.<br />
<br />
= How to use Path Nodes =<br />
<br />
Path nodes are placed like any other entity (RMB and select "add entity", then scroll to "paths"). They show up as an orange box in the editor.<br />
<br />
Path nodes are useless if they are not linked to another entity (either an AI or another node). In order to link them, you use the "target" property. This tells the AI what pathnode they should go to (or act on) next. If you type "target" "path_corner_1" in your AI property list, then your AI will walk to "path_corner_1" when the map starts. Without a "target" property, your AI will not go anywhere. Once you add a "target" property to either your AI or another node, you should see an orange line connecting the two entities.<br />
<br />
Behaviour nodes activate behaviour in order. In other words, if you want an AI to reach a path_corner, then turn to face a direction, then wait for a time, then play an animation, you need to link the nodes in that order. <br />
<br />
path_corner ---> path_turn ----> path_wait ----> path_cycleanim -----> next path_corner<br />
<br />
It is also possible to target multiple nodes (using "target_1", "target_2" etc. spawn args). In this case, the AI will choose one of these nodes with equal probability. <br />
If the '''"chance"''' spawn arg (between 0 and 1) is set on a node, it defines the probability for the AI to choose this path node next when multiple path nodes are targetted.<br />
<br />
There are now two new spawnargs, '''"alert_idle_only"''' and '''"idle_only"''' that can be set on path nodes. The nodes are then only chosen when the AI is in that state. For example, if you set a path_corner as "idle_only", then the AI will no longer go to that path node when it has been alerted. This allows the mapper to set a complete set of alternate patrols and actions for AI who have been alerted (like sending them to guard important areas).<br />
<br />
<br />
<br />
== path_corner ==<br />
Probably the most common path node, this is a "travel node". AI will walk from their current position to this node in as straight a line as possible. This node must be on the ground and in an area AI can reach. See [[Pathfinding]] for more information on how to help AI go from one node to another.<br />
<br />
To make AI patrol an area, each path_corner node can target the next one in sequence. If AI reach a node that does not target anything, they will stop there and no longer move without player interaction. It is possible for two path_nodes to target each other, which means the AI will walk from one to the other and back again endlessly.<br />
<br />
A single entity (path node or AI) can target more than one path_corner; D3 will randomly choose between the targetted nodes. Use the following syntax: ''(actually this syntax needs to be double checked)''<br />
<br />
target path_corner_1<br />
target_2 path_corner_2<br />
<br />
<br />
''(At the moment, targetting more than 2 path_corners from the same entity does not seem to work (possibly a DR bug).''<br />
<br />
In the example below, both A and B are path_corner nodes. On map start, the AI will walk to A, then turn and walk to B, then stop.<br />
<br />
[[image:pathfinding2.jpg]]<br />
<br />
<br />
'''Note that an AI will return to a path_corner ''(does it choose the nearest or most recent?)'' after a failed search. If you do not have at least one path_corner, the AI will stop wherever they are when their search is complete.'''<br />
<br />
== path_wait ==<br />
<br />
This is a behaviour node. It does not tell an AI to move anywhere. This node tells an AI to wait in an idle state for a given amount of time. Once that time is up, the AI will proceed to whatever the next target is (a path_wait with no target is pretty pointless). <br />
<br />
A path_wait node appears as a small orange box. It has a directional arrow, but that has no affect on which direction the AI faces in the first place. You can set the angle key on the path either by rotating the entity or by setting the key directly to make the AI turn and face this direction before starting to wait.<br />
<br />
A path_wait node should have a "wait" property (it's possible there is a default wait value if you don't add one), with the number of seconds the AI should wait there before proceeding. It can also have a "wait_max" property which will vary the repeat time. So for example...<br />
<br />
* wait 30<br />
* wait_max 40 <br />
<br />
...will cause the AI to wait between 30 to 40 seconds before proceeding. If wait_max is set to 0, the AI will always wait exactly the time specified in wait before proceeding.<br />
<br />
In the following example, A and B are path_corners, and the small orange box is a path_wait entity. On map start, the AI will walk to A and wait there for the required amount of time, then turn and proceeds to B.<br />
<br />
[[image:pathfinding3.jpg]]<br />
<br />
Note that it does not matter '''where''' the path_wait node is placed. The AI does not actually follow the orange lines (this is not really intuitive, I know). The example below would cause the exact same behaviour as the example above--in both cases the AI will walk directly from A to B.<br />
<br />
[[image:pathfinding4.jpg]]<br />
<br />
<br />
<br />
Another useful example for path_wait is that of the stationary guard who turns to look in different directions periodically. This can be schematically represented (arrows indicate target links) as:<br />
<br />
AI -> path_corner1 -> path_wait1 -> path_wait2 -> path_corner1<br />
<br />
Example properties for the path_wait are:<br />
wait: 5 (minimum time to wait on action)<br />
wait_max: 10 (maximum time to wait on action)<br />
angle: 0 ('''Important''': this property is essential for proper function even if the angle is 0)<br />
<br />
<br />
The AI walks to or stands at the path_corner. The next action is to do what is indicated by the first path_wait. In this example, it tells the AI to face a particular direction for a certain period of time. This then targets a second path_wait which has the AI face a different direction for a certain period of time. To complete the cycle, the second path_wait then targets the original path_corner. The path_corners are necessary because again, the path_wait doesn't contain pathing or location information. Without the path_corner, if the AI is caused to wander (e.g. becomes alerted), it might not return to the original standing spot, and instead will do the look angles right where it stands. The path_corner assures the AI returns to its original position.<br />
<br />
== path_turn == <br />
<br />
This behaviour node tells an AI to turn in place to face a chosen direction. It does not make the AI walk anywhere. This is the one node where the directional arrow does seem to matter--the AI turns to face the same direction as the arrow. Alternately, you can use the property "angle" and the values below:<br />
<br />
* 0 = East (X)<br />
* 90 = North (Y)<br />
* 180 = West (-X)<br />
* 270 = South (-Y)<br />
* 360 = East(X)<br />
<br />
(Actually, to be more accurate, rotating the entity automatically adds the "angle" property to the entity. If you just leave the arrow facing the way it is when you create the entity, there will be no "angle" property, and therefore the AI will not turn.)<br />
<br />
== path_anim ==<br />
<br />
This is a behaviour node that makes the AI play an animation, once. When that animation is done, it proceeds to the next target (if any). This could be used to make an AI walk over to a bookshelf and play a 'reaching out' animation, for example. <br />
<br />
The syntax proper syntax is:<br />
<br />
anim [animation name]<br />
<br />
You can see the list of animations names in the AI's def file. Do not use the name of the actual animation file. <br />
<br />
A path_anim can have only one animation, but it is possible for a single entity to target more than one path_anim. The AI will pick one of the path_anim nodes at random and play that animation.<br />
<br />
When you first create the path_anim entity, the directional arrow is meaningless. However, if you rotate the entity, the "angle" property is added to the entity and is updated based on which direction the arrow is pointing. That property indicates the direction the AI will face while playing the animation.<br />
<br />
'''Issues:''' Currently there are two problems with path_anim nodes. First, the animation seems to be played only on the torso channel (ie, it will not affect the AI's legs). Secondly, a random idle animation can interrupt the path_anim. Not only will this cut off the desired animation, but ''the AI will not proceed to the next target'' (pretty serious). ''[edit: this latter issue should be fixed now]''<br />
<br />
== path_sit ==<br />
<br />
This is a behaviour node that makes the AI sit down at its current location. See [[Sitting Behaviour for AI]] for more information.<br />
<br />
= Untested Nodes =<br />
<br />
I have not personally tested the following, so I'm just going by their editor descriptions. They may or may not work as described.<br />
<br />
<br />
== path_cycleanim ==<br />
<br />
The AI stays in place and loops the selected animation, either for a specified amount of time (using the 'wait' property) or until triggered. Syntax needed.<br />
<br />
== path_lookat ==<br />
<br />
This does not stop the AI, but they will turn their head and look somewhere specific as they walk to their next target. For the next ''wait'' seconds, turn head to look at the entity given by the ''focus'' spawnarg (defaults to looking at the path_lookat entity itself). This is useful if you want to make sure an AI is looking at a specific spot (or away from a certain spot) during their patrol.<br />
<br />
== path_waitfortrigger ==<br />
<br />
Waits at a given place until triggered, then proceeds to the next target. This is useful if you want some control over exactly where the AI is when the players first see it.<br />
<br />
== path_hide ==<br />
<br />
Deactivates and stops rendering the AI. Used to remove "ambient AI" from the map when they have served their purpose (ie, AI that are just there for flavour, like a messenger leaving the room and disappearing).<br />
<br />
== path_show ==<br />
<br />
Starts rendering the AI. I would assume this one would be linked to a path_waitfortrigger, to create AI that spawn when triggered. This could be used to create the effect that an AI just came through a doorway or around a corner.<br />
<br />
== path_attack ==<br />
<br />
Used to script AI attacking a particular enemy, for scripted sequences I guess. AI will continue on to the next path entity if it kills the enemy.<br />
<br />
Questions: How do you define who the AI attacks?<br />
<br />
[Fidcal]: Just found this - "Character will attack the character specified by 'enemy' key. Character will go to next path when enemy dies or when activated." Not tested.<br />
<br />
== path_interact ==<br />
<br />
This lets the AI interact with an entity (for example a button) in a similar way to frobbing. This will only work for buttons etc, not for inventory items and moveables. The AI will stop and look at the entiy while interacting, but not walk to it, so a path_corner next to the entity is required. AI will use normal doors and elevators without needing a path_interact (confirmation needed). However, this could be used to make AI turn on lightswitches, open mechanical doors, etc.<br />
<br />
Questions: what is the synatx for targetting the entity to interact with? How close does the AI need to be?<br />
<br />
{{tutorial-editing}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Path_Nodes&diff=8516Path Nodes2009-06-22T09:14:14Z<p>Angua: /* How to use Path Nodes */</p>
<hr />
<div>''originally written by Springheel''<br />
<br />
For more information on pathfinding, see [[Pathfinding]].<br />
<br />
= What are Path Nodes? =<br />
<br />
Path entities (or path nodes) are the things that you use to make your AI move around the map. Placing path nodes can take a little getting used to; hopefully this article will help (I'm far from an expert, but here's what I've discovered so far).<br />
<br />
There are lots of different kinds of path nodes. It can sometimes help to think of them as "travel nodes" (nodes that AI will travel to) and "behaviour nodes" (nodes that tell AI how to behave at a certain point). <br />
<br />
Although path nodes have a directional arrow in the editor, it has no impact on most nodes. Rotating the node does add a corresponding "angle" property to the entity (matching the direction of the arrow). Certain nodes (path_anim and path_turn, for example) are affected by the "angle" property, but most will ignore it.<br />
<br />
= How to use Path Nodes =<br />
<br />
Path nodes are placed like any other entity (RMB and select "add entity", then scroll to "paths"). They show up as an orange box in the editor.<br />
<br />
Path nodes are useless if they are not linked to another entity (either an AI or another node). In order to link them, you use the "target" property. This tells the AI what pathnode they should go to (or act on) next. If you type "target" "path_corner_1" in your AI property list, then your AI will walk to "path_corner_1" when the map starts. Without a "target" property, your AI will not go anywhere. Once you add a "target" property to either your AI or another node, you should see an orange line connecting the two entities.<br />
<br />
Behaviour nodes activate behaviour in order. In other words, if you want an AI to reach a path_corner, then turn to face a direction, then wait for a time, then play an animation, you need to link the nodes in that order. <br />
<br />
path_corner ---> path_turn ----> path_wait ----> path_cycleanim -----> next path_corner<br />
<br />
It is also possible to target multiple nodes (using "target_1", "target_2" etc. spawn args). In this case, the AI will choose one of these nodes with equal probability. <br />
If the '''"chance"''' spawn arg (between 0 and 1) is set on a node, it defines the probability for the AI to choose this path node next when multiple path nodes are targetted.<br />
<br />
There are now two new spawnargs, '''"alert_idle_only"''' and '''"idle_only"''' that can be set on path nodes. The nodes are then only chosen when the AI is in that state. For example, if you set a path_corner as "idle_only", then the AI will no longer go to that path node when it has been alerted. This allows the mapper to set a complete set of alternate patrols and actions for AI who have been alerted (like sending them to guard important areas).<br />
<br />
<br />
<br />
== path_corner ==<br />
Probably the most common path node, this is a "travel node". AI will walk from their current position to this node in as straight a line as possible. This node must be on the ground and in an area AI can reach. See [[Pathfinding]] for more information on how to help AI go from one node to another.<br />
<br />
To make AI patrol an area, each path_corner node can target the next one in sequence. If AI reach a node that does not target anything, they will stop there and no longer move without player interaction. It is possible for two path_nodes to target each other, which means the AI will walk from one to the other and back again endlessly.<br />
<br />
A single entity (path node or AI) can target more than one path_corner; D3 will randomly choose between the targetted nodes. Use the following syntax: ''(actually this syntax needs to be double checked)''<br />
<br />
target path_corner_1<br />
target_2 path_corner_2<br />
<br />
<br />
''(At the moment, targetting more than 2 path_corners from the same entity does not seem to work (possibly a DR bug).''<br />
<br />
In the example below, both A and B are path_corner nodes. On map start, the AI will walk to A, then turn and walk to B, then stop.<br />
<br />
[[image:pathfinding2.jpg]]<br />
<br />
<br />
'''Note that an AI will return to a path_corner ''(does it choose the nearest or most recent?)'' after a failed search. If you do not have at least one path_corner, the AI will stop wherever they are when their search is complete.'''<br />
<br />
== path_wait ==<br />
<br />
This is a behaviour node. It does not tell an AI to move anywhere. This node tells an AI to wait in an idle state for a given amount of time. Once that time is up, the AI will proceed to whatever the next target is (a path_wait with no target is pretty pointless). <br />
<br />
A path_wait node appears as a small orange box. It has a directional arrow, but that has no affect on which direction the AI faces. <br />
<br />
A path_wait node should have a "wait" property (it's possible there is a default wait value if you don't add one), with the number of seconds the AI should wait there before proceeding. It can also have a "random" property which will vary the repeat time. Random n varies the wait time randomly by plus or minus n seconds. So for example...<br />
<br />
* wait 30<br />
* random 10 <br />
<br />
...will cause the AI to wait between 20 to 40 seconds before proceeding.<br />
<br />
In the following example, A and B are path_corners, and the small orange box is a path_wait entity. On map start, the AI will walk to A and wait there for the required amount of time, then turn and proceeds to B.<br />
<br />
[[image:pathfinding3.jpg]]<br />
<br />
Note that it does not matter '''where''' the path_wait node is placed. The AI does not actually follow the orange lines (this is not really intuitive, I know). The example below would cause the exact same behaviour as the example above--in both cases the AI will walk directly from A to B.<br />
<br />
[[image:pathfinding4.jpg]]<br />
<br />
<br />
<br />
Another useful example for path_wait is that of the stationary guard who turns to look in different directions periodically. This can be schematically represented (arrows indicate target links) as:<br />
<br />
AI -> path_corner1 -> path_wait1 -> path_wait2 -> path_corner1<br />
<br />
Example properties for the path_wait are:<br />
wait: 5 (minimum time to wait on action)<br />
wait_max: 10 (maximum time to wait on action)<br />
angle: 0 ('''Important''': this property is essential for proper function even if the angle is 0)<br />
<br />
<br />
The AI walks to or stands at the path_corner. The next action is to do what is indicated by the first path_wait. In this example, it tells the AI to face a particular direction for a certain period of time. This then targets a second path_wait which has the AI face a different direction for a certain period of time. To complete the cycle, the second path_wait then targets the original path_corner. The path_corners are necessary because again, the path_wait doesn't contain pathing or location information. Without the path_corner, if the AI is caused to wander (e.g. becomes alerted), it might not return to the original standing spot, and instead will do the look angles right where it stands. The path_corner assures the AI returns to its original position.<br />
<br />
== path_turn == <br />
<br />
This behaviour node tells an AI to turn in place to face a chosen direction. It does not make the AI walk anywhere. This is the one node where the directional arrow does seem to matter--the AI turns to face the same direction as the arrow. Alternately, you can use the property "angle" and the values below:<br />
<br />
* 0 = East (X)<br />
* 90 = North (Y)<br />
* 180 = West (-X)<br />
* 270 = South (-Y)<br />
* 360 = East(X)<br />
<br />
(Actually, to be more accurate, rotating the entity automatically adds the "angle" property to the entity. If you just leave the arrow facing the way it is when you create the entity, there will be no "angle" property, and therefore the AI will not turn.)<br />
<br />
== path_anim ==<br />
<br />
This is a behaviour node that makes the AI play an animation, once. When that animation is done, it proceeds to the next target (if any). This could be used to make an AI walk over to a bookshelf and play a 'reaching out' animation, for example. <br />
<br />
The syntax proper syntax is:<br />
<br />
anim [animation name]<br />
<br />
You can see the list of animations names in the AI's def file. Do not use the name of the actual animation file. <br />
<br />
A path_anim can have only one animation, but it is possible for a single entity to target more than one path_anim. The AI will pick one of the path_anim nodes at random and play that animation.<br />
<br />
When you first create the path_anim entity, the directional arrow is meaningless. However, if you rotate the entity, the "angle" property is added to the entity and is updated based on which direction the arrow is pointing. That property indicates the direction the AI will face while playing the animation.<br />
<br />
'''Issues:''' Currently there are two problems with path_anim nodes. First, the animation seems to be played only on the torso channel (ie, it will not affect the AI's legs). Secondly, a random idle animation can interrupt the path_anim. Not only will this cut off the desired animation, but ''the AI will not proceed to the next target'' (pretty serious). ''[edit: this latter issue should be fixed now]''<br />
<br />
== path_sit ==<br />
<br />
This is a behaviour node that makes the AI sit down at its current location. See [[Sitting Behaviour for AI]] for more information.<br />
<br />
= Untested Nodes =<br />
<br />
I have not personally tested the following, so I'm just going by their editor descriptions. They may or may not work as described.<br />
<br />
<br />
== path_cycleanim ==<br />
<br />
The AI stays in place and loops the selected animation, either for a specified amount of time (using the 'wait' property) or until triggered. Syntax needed.<br />
<br />
== path_lookat ==<br />
<br />
This does not stop the AI, but they will turn their head and look somewhere specific as they walk to their next target. For the next ''wait'' seconds, turn head to look at the entity given by the ''focus'' spawnarg (defaults to looking at the path_lookat entity itself). This is useful if you want to make sure an AI is looking at a specific spot (or away from a certain spot) during their patrol.<br />
<br />
== path_waitfortrigger ==<br />
<br />
Waits at a given place until triggered, then proceeds to the next target. This is useful if you want some control over exactly where the AI is when the players first see it.<br />
<br />
== path_hide ==<br />
<br />
Deactivates and stops rendering the AI. Used to remove "ambient AI" from the map when they have served their purpose (ie, AI that are just there for flavour, like a messenger leaving the room and disappearing).<br />
<br />
== path_show ==<br />
<br />
Starts rendering the AI. I would assume this one would be linked to a path_waitfortrigger, to create AI that spawn when triggered. This could be used to create the effect that an AI just came through a doorway or around a corner.<br />
<br />
== path_attack ==<br />
<br />
Used to script AI attacking a particular enemy, for scripted sequences I guess. AI will continue on to the next path entity if it kills the enemy.<br />
<br />
Questions: How do you define who the AI attacks?<br />
<br />
[Fidcal]: Just found this - "Character will attack the character specified by 'enemy' key. Character will go to next path when enemy dies or when activated." Not tested.<br />
<br />
== path_interact ==<br />
<br />
This lets the AI interact with an entity (for example a button) in a similar way to frobbing. This will only work for buttons etc, not for inventory items and moveables. The AI will stop and look at the entiy while interacting, but not walk to it, so a path_corner next to the entity is required. AI will use normal doors and elevators without needing a path_interact (confirmation needed). However, this could be used to make AI turn on lightswitches, open mechanical doors, etc.<br />
<br />
Questions: what is the synatx for targetting the entity to interact with? How close does the AI need to be?<br />
<br />
{{tutorial-editing}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Doors&diff=8515Doors2009-06-22T08:50:52Z<p>Angua: /* AI Door management */</p>
<hr />
<div>{{todo}}<br />
''Written by Fidcal'' ''edit Baddcog''<br />
<br />
==Quick Summary==<br />
<br />
Quick way to get an unlocked door in your map:<br />
<br />
* Create a door from the entity list<br />
* Use the "skin" spawnarg on the door to change its appearance. <br />
* Create a handle from the entity list<br />
* Add the ''door_handle'' property to the door and give it the name of the handle<br />
* To the door handle add the value frob_peer and use the name of the door.<br />
* To open clockwise, change the ''rotate'' property from <code>0 90 0</code> to <code>0 -90 0</code><br />
<br />
==Introduction==<br />
<br />
This tutorial explains how to put doors into your map using Dark Radiant, as well as adjust them and their properties.<br />
<br />
The rest of this tutorial assumes that you have a basic understanding of using DarkRadiant. If you haven't done so, please go read the [[Dark Radiant Must Know Basic Intro]] article first.<br />
<br />
Additionally:<br />
<br />
* Up, down, left, and right in Dark Radiant's ''top'' orthoview are regarded here as the standard map directions of North, South, East, and West where useful for clarity.<br />
* Where the term ''brush'' is used with a door it mostly also applies to a door made up of a group of brushes and/or patches.<br />
* Where the term ''door'' is used it often will also apply to any object you wish to rotate when frobbed, for instance an openable window, box lid, or even more exotic objects that the imaginative mapper might conceive like a signal, engine part, toy, or whatever. So long as it needs to turn or slide just a fixed amount when frobbed then return when frobbed again then the following applies.<br />
<br />
==Door types==<br />
<br />
All tangible objects in Dark Mod are ''entities'', having either a pre-made model shape or else brush/patch(es). So there are two ways to create a door in Dark Radiant: as a model door or a textured brush door (or a hybrid of the two).<br />
<br />
Models are ready made door objects but cannot within Dark Radiant (at the time of writing) be resized, rescaled, cropped or clipped whereas brushes are very flexible in that respect and can be worked into custom shapes for your map, including secret doors that blend into walls and other surfaces.<br />
<br />
Most of the current door models are found in two places along with the door handles.<br />
*Model Viewer: doors created from here will be static in the world and have no props other than material type.<br />
You can add any props to them to make them working doors. If nothing else it is a good place to view the different size and skin options for the doors.<br />
*Entity List: most of the door models can be found here. These doors have properties already assigned so they are ready to be used. Only one base door of each type is listed, create the size/hinge count door you want (2 hinge doors have a 'no hinge' skin). You can choose a skin for the door once it has been created in the editor with the "skin" spawnarg (use the model name of the door you want, taken from the model list, as its value). This is the easiest way to create a door. The same goes for door handles.<br />
<br />
Remember also that door functions may be applied to objects other than doors for instance to openable windows, drawbridges, gates, in fact anything that needs a partial rotation or slide when frobbed then return when frobbed again such as a signal device. Lockboxes and chests use similar properties.<br />
<br />
Door/handle prefabs seem to crash Doom3 when trying to reload a map so far now just create and link each door/handle. You can create one set and copy/paste them, but you need to take great care that all the name props are changed to match each clone. Otherwise you get handles that fly off with a distant door and handles that don't move.<br />
<br />
==Creating a Door==<br />
<br />
Put simply, to make a door you will be creating an 'entity with model' or 'entity with brush' or some variation thereof.<br />
<br />
===Creating a Model Door===<br />
<br />
There are several approaches to making a model door; the simplest is to create a door from the entity list; or create a door from the model viewer (good for static unusable prop doors).<br />
<br />
'''Entity List''':<br />
<br />
*Deselect everything in editor by hitting the Esc button<br />
*Right-click an ortho view and select Create Entity<br />
*Navigate to darkmod/movers/''atdm:door_...'', choose the door you want<br />
*Click Add<br />
*To change its appearance, add a "skin" spawnarg to the door, with the value being the model name of the door you want.<br />
<br />
You now have a workable door in your level.<br />
<br />
'''Model Viewer''':<br />
<br />
* Right click in the orthoview, select ''Create Model'' then <code>darkmod</code> and select a door.<br />
* Note that you can left drag the image in the ''Choose Model'' dialog to rotate it around.<br />
* Click [[Image:Button ok.png]] and you have a static door.<br />
* If you want to make it work (openable, frobbable) then:<br />
** Select the entity inspector,<br />
** Select the top classname line so it highlights<br />
** Select the func_static line in the input box ''below'' the properties window.<br />
** Edit <code>func_static</code> to <code>atdm:mover_door</code><br />
** Click {{check}} or press {{key-enter}}<br />
<br />
Alternatively you can do it the old way:<br />
<br />
* Create any temporary brush<br />
* Right click in orthoview and select <code>Create Entity</code> then <code>atdm:mover_door</code>.<br />
* Left lick the model name line in the entity inspector.<br />
* Below it on the ''Entity Inspector'' panel you should now see a button 'Choose Model'<br />
* Left click it, select a door model from the darkmod group.<br />
* Note that you can left drag the image in the ''Choose Model'' dialog to rotate it around.<br />
* The temporary brush was deleted.<br />
<br />
<br />
In all three instances, you now have a working door with default properties. <br />
<br />
Name your door by adding the prop (or modifing it) to name ''My_Door_1''. You can use any name that you feel is appropriate but all doors with handles attached ''must'' have their own specific name. Use the name My_Door_1 for your first attempt as it will be referenced when you get around to attaching handles (see below).<br />
<br />
To add a handle and other adjustments, see [[#Customising and Adjusting Door Properties]] below.<br />
<br />
===Creating a Textured Brush Door===<br />
<br />
'''Tip:''' If unsure of size then you might insert a temporary human AI first to get a sense of height.<br />
<br />
==== The simplest brush door: ====<br />
<br />
* Drag out a new brush to the size required, eg, a seven foot high door is 84" x 1.1 = about 90 units in Dark Radiant.<br />
* Give it a door texture from the texture browser (or wall texture for a secret door)<br />
* Right click in orthoview and select ''Create Entity'' then <code>atdm:mover_door</code><br />
* You now have a default door that rotates around its center.<br />
<br />
To move the rotation point to the door edge and other adjustments, see [[#Customising and Adjusting Door Properties]] below.<br />
<br />
==== Multi-brush doors: ====<br />
<br />
More complex multi-brush doors can be created using the [[Clipper]] tool, CSG, etc. - this is not covered in this tutorial. Then assign <code>atdm:mover_door</code> for that whole brush structure. Also you can collect various brushes positioned together in relation to one another as needed, select them all, then assign <code>atdm:mover_door</code> for the group. All the brushes will be children of the <code>atdm:mover_door</code> entity and will rotate and be frobbable, etc. as one unit, as one door. To add further brushes or even model shapes later see the section on [[#Adding handles and other items to doors]].<br />
<br />
Name your door by adding the prop (or modifing it) to name My_Door_1. You can use any name that you feel is appropriate but all doors with handles attached must have their own specific name. Use the name My_Door_1 for your first attempt as it will be referenced when you get around to attaching handles (see below). (repeated from above in case you didn't choose to create a model door)<br />
<br />
=== Double Doors ===<br />
Double doors are automatically recognised by the code when the doors are spawned. The prerequisite is that both doors are sharing/touching the same visportal. The spawnarg ''auto_setup_double_door'' (which defaults to "1") will take care of setting up the open/lock peer relationship between the two doors. The doors will open/close and lock/unlock along with each other as a result.<br />
<br />
What happens behind the scenes: the doors are adding each other to their internal open_peer and lock_peer list, which causes the double doors to perform the same action when frobbed or used.<br />
<br />
Note that ''auto_setup_double_door'' will not set the frob_peer relationship, i.e. each door will frob-highlight on its own without highlighting the other door. You'll need to add that spawnarg manually if you want to highlight the entire double door as one.<br />
<br />
==Customising and Adjusting Door Properties==<br />
<br />
Handles, lockplates, etc. can be added to doors and door properties can be adjusted for rotation, sliding, locking, and more.<br />
<br />
Some of the door models have hinge plates and lockboxes that are reskinnable with a good variety of skins.<br />
<br />
===Door handles and other door attachments===<br />
<br />
You can add handles and other items to doors such that they move correctly with the door whether rotating, sliding, or both and even if the door is not vertical such as a skylight or trapdoor.<br />
Handle models come in two types, ''single handles'' and ''double handles''. A single handle is one sided, this means the handle will be inside the door or outside the door, but not both. A double handle has a lever on the inside of the door and a handle on the outside of the door. Each has benefits.<br />
<br />
*'''''Single door handles''''':<br />
Single door handles can be used on a static door, a door that's just for show that no AI's or the player can use. In this case you should just create a door handle from the model viewer, it will be static and have no properties such as scripts. It is for looks only.<br />
<br />
Single handles can also be used inside AND outside of the same door to save on rendering. Unlike the double handles the handle on the inside of a portal won't render. The curved handle is only about 130 polys per side, but if you have a large area and 10 handles you can save 1,000 polys from being rendered. Everything counts when it comes to performance.<br />
I will call this ''multiple handles'', see more below.<br />
<br />
These can also be useful on brush doors created in the editor that may be very thin or very wide.<br />
<br />
*'''''Double door handles''''':<br />
These are models have have a handle inside and outside. The bonus is that they only use one entity. Maps are limited to about 4,000 entities but when you count lights, AI, sound speakers, ect... you can run out of entities quickly on a large map. If you plan on building a large map this is the way to go, even in a small map they have benefits, namely that you only have to attach one handle per door.<br />
<br />
Whether you decide to use a single handle or a double handle you must first follow the instructions below and attach one handle first. If you choose a double handle, follow the instructions below and you are done. If you choose a single handle type follow the instructions then also follow the ''multiple handle'' instructions for the second handle.<br />
<br />
Both single and double handle types can be found in two places. The model viewer which will create a static model good for show, you can manually add props to make them work OR you can look in the entity browser.<br />
Using a handle from the entity browser saves you a little bit of time as some props are already added, you just need to add the frob_peer names for the doors/handles and the door_handle name to the door.<br />
<br />
<br />
=== Adding a working model door handle===<br />
<br />
Quick summary:<br />
* Create a model or brush handle and make it an ''atdm:mover_door_handle'' entity.<br />
* Position it on your door. Use the opposite side from the door's multicolor X-Y-Z indicator (highlight the door to see it) if it's not obvious which side it goes on. <br />
* '''Bind''' the handle to the door<br />
* It should now be a working handle though may need adjustments of rotation etc. see later. <br />
<br />
<br />
Important: read preceding section on door handle types and performance issues first.<br />
<br />
This works with both a model door and a brush door:<br />
<br />
'''Rotation''':<br />
* By default the door handle entity rotates ''anti-clockwise'' (looked at from the front) then springs back. A ''double handle'' model is OK but two singles (see ''Multiple door handles'' below) need more care as only one is the functioning entity and the other is just attached to it. So anti-clockwise is fine for a door with its hinge on the left and the handle on the right - the handle will rotate down then spring back. If you put the functioning door handle on the other side you will have to change the default ''rotate'' property from -45 0 0 to 45 0 0. '''''Therefore it is easier to generally put this handle on the side of the door where the hinge is on the left and the non-functioning attachment handle on the other side.'''''<br />
*If your door only needs one handle, eg, a cupboard door, and from outside its hinge is on the right then you will need to change the ''rotate'' property of the handle as described above.<br />
<br />
'''''The functioning handle entity:'''''<br />
* Create an entity door handle (movers folder) or create a brush or model handle and assign it the entity ''atdm:mover_door_handle''.<br />
* Position it where you wish on your door.<br />
* '''Bind''' the handle to the door, by adding the "bind" spawnarg to the handle.<br />
<br />
You now have a working door handle with default properties.<br />
<br />
*'''Multiple door handles''':<br />
Now that you've got a handle attached to one side of the door it is time to add one to the other side (unless you used a double handle).<br />
* Create the new handle. The single handles come in left and right persuasions. A door needs a left facing handle on one side and a right facing handle on the other, so if you have already added the left handle create a right handle and line it up on the other side of the door.<br />
* Name this handle. I prefer to keep a naming convention for each door and it's respective handles, it makes things alot easier. The door is named '''My_Door_1''', the first handle is named '''My_Handle_1''' so name the second handle '''My_Handle_1_1'''. This will make it stay with the first handle in the entity list. This is important to keep organized. If you name it My_Handle_2 then when you get to another door named My_Door_2 you'll be confused.<br />
* Place and '''bind''' that handle to your door.<br />
<br />
You now have two single door handles on either side of the door that rotate together as if they were physically attached.<br />
<br />
'''To add a brush to a brush door''':<br />
* Select the new brush ''and'' the brush door all together; ''the entity '''must''' be selected '''last'''.''<br />
* Use {{menu|Edit|Reparent primitives}}. This ensures the parent entity adopts the new item(s).<br />
* If you have trouble selecting them in the orthoview because other brushes, etc. get selected then try in the camera view or as a last resort move them temporarily to an open area (but keep them in the same positions relative to each other.) Use {{key-shift}}+{{LMB}} on new item(s) then {{key-shift}}+{{LMB}} on main entity. Once they are all selected, use the {{menu|Edit|Reparent primitives}}.<br />
<br />
'''To add ''model'' static items''': knockers, hinges, static handles etc. to a ''Model Door'':<br />
* Select item<br />
* Right click in orthoview and select ''Create Entity'' then <code>entity func_static</code><br />
* Position it where you wish on your door.<br />
* To synchronize this with your particular door you need to add the property ''bind'' and the individual door name to the brush entity. To do this...<br />
** Select the model door.<br />
** In the entity inspector, select the ''name'' line<br />
** Select the bottom line in the input box ''below'' the properties window.<br />
** Copy the name<br />
** Deselect the door with {{key-esc}}<br />
** Select the brush entity<br />
** Add a property "bind" to it.<br />
** Change the value of the property by pasting in the door name<br />
** Click {{check}} or press {{key-enter}}<br />
<br />
'''To add ''brush'' static items''': knockers, hinges, static handles to a Model Door:<br />
* This method is not ideal but it seems to work OK.<br />
* Select the brush.<br />
* Right click in orthoview and select Create Entity then ''atdm:mover_door_handle''<br />
* Position it where you wish on your door.<br />
<br />
To synchronize this with your particular door you need to add the property ''door_handle'' on the door, and give as the value the name of the brush you just created.<br />
<br />
This brush turns like a handle. To stop it:<br />
<br />
* Adding ''rotate 0 0 0'' or disabling the handle script won't help.<br />
* Add a real working handle (as in the section above ''To add a working model door handle...'' and it must be added LAST.)<br />
<br />
If you don't want too see a real working handle added maybe try another tiny brush with the handle function and hide it inside the door?<br />
<br />
===Locking Doors===<br />
<br />
To lock a door check the ''show inherited properties'' in the entity inspector for a ''atdm:mover_door'' entity and you should see the ''locked'' property. Select it and in the input box below the properties you can change its value:<br />
<br />
* 0 = unlocked (default)<br />
* 1 = locked<br />
<br />
If locked it will require an entity that is associated with it to be able to act as a key to unlock it.<br />
<br />
Currently door handles on locked doors will rotate when frobbed, they will bounce back though and the door will stay locked until unlocked.<br />
<br />
===Keys===<br />
<br />
Assigning specific keys to specific doors is simple.<br />
<br />
* The key is just a func_static model or brush. All keys can be found in the Entity List, these keys have all required props, they just need to be named.<br />
<br />
If you create a key from the Model Viewer and want it to be useable<br />
* Make sure it has the properties:<br />
useable 1 [so it can be used by the door]<br />
frobable 1<br />
inv_name <unique name><br />
inv_category Keys<br />
inv_target player1<br />
inv_icon guis/assets/hud/inventory_icons/<icon name><br />
inv_stackable 0 or 1 where 1 can be used on all copies of the same key so they show as one entry in the inventory with a total.<br />
<br />
Add to the door the property <code>used_by</code> with the key as the value. Multiple keys can open the same door by using several <tt>used_by</tt> spawnargs:<br />
<br />
"used_by" "doorkey_1"<br />
"used_by1" "doorkey_2<br />
<br />
====Master Key for Testing====<br />
<br />
By default, ALL locks can be opened by any key named ''key_master''. Just create a key in your map, name it ''key_master'' and it becomes a master key for use while testing. Add inv_map_start 1 to it so it is in the player inventory at game start. Remember to delete it when your mission is finished.<br />
<br />
===Lockpicks===<br />
''by Baddcog''<br />
<br />
This section may need reviewing but is essentially correct<br />
<br />
To make a door ''lockpickable'' check the ''show inherited properties'' in the entity inspector for a ''atdm:mover_door'' entity and you should see the ''pickable'' property. Select it and in the input box below the properties you can change its value:<br />
<br />
* 0 = unpickable<br />
* 1 = pickable (default)<br />
<br />
If pickable then the door can be opened with a lockpick...<br />
<br />
There are four lock pick types.<br />
*'''S'''=snake<br />
*'''C'''=circular or round<br />
*'''B'''=bent<br />
*'''T'''=triangular<br />
<br />
A lock can be set with many pins and each pin needs a designated lockpick type (see above). Keep in mind that the lockpicking in The Darkmod is much more involved than in T2 or T3. You have more lockpicks, an infinite amount of pins and the player has to listen to sounds to know when a lock is pin is picked.<br />
<br />
This means that authors can be very evil and really frustrate the player, in which case their missions will probably not be played. So be nice to the player and don't waste your time. Use simple locks for the most part and save complicated locks for important sections and to build tension. Don't make the player use four lockpicks and have 20 pins to pick. In most cases 1 or 2 pins will suffice and it isn't necessary to include all four lockpicks with every mission.<br />
Also try to include a lock lever on lockboxes or chests, door handles will rotate as the pins are being picked. This gives the player visual clues to help with the picking.<br />
IMO this system is a huge leap foward for lockpicking but also has the ability to completely frustrate the player as stated above. Keep this in mind when designing your lockpick systems.<br />
<br />
These props go on the door itself, or the lid of a chest.<br />
*'''lock_pins''' 1327<br />
*'''lock_picktype''' bcst<br />
<br />
The lockpins property specifies how many pins each lockpicktype has.<br />
The lockpick_type property specifies how many times the player has to switch picks and which pick they have to use.<br />
<br />
So looking at the example above we have lockpick _type b(bent),c(circular),s(snake), and t(triangular). The player will have to use these lockpicks in this order. Once the bent lockpicks pins are open the player can advance to the circular pick and so forth.<br />
In the example above the lockpins specify in order which pick types have how many pins, so the b pick has 1 pin, the c pick has 3 pins, the s pick has 2 pins, the t pick has 7 pins.<br />
This is a VERY EVIL lock and the player will probably spend twenty minutes trying to pick it before they come knock down your door. This is exactly the type of lock you don't want to add to your map.<br />
<br />
*For most simple locks like a footlocker with some broadhead arrows a good lock type would be something like:<br />
<br />
lock_pins 2<br />
<br />
lock_picktype b<br />
<br />
*or:<br />
<br />
lock_pins 21<br />
<br />
lock_picktype ts<br />
<br />
*or:<br />
<br />
lock_pins 11<br />
<br />
lock_picktype cc<br />
<br />
*For more complicated locks you might want to use more picks, but not too many pins:<br />
<br />
lock_pins 11111<br />
<br />
lock_picktype tsbsc<br />
<br />
That's only one pin per type, but it is 5 types (a repeat on the snake pick) and could still take the player a bit of time to work through.<br />
<br />
lockpick_rotate - is placed on the door. It is the amount the visible rotating handle or pin rotates while picking.<br />
<br />
lockpick_translate - is placed on the door. It is the amount the visible handle or pin moves in a straigh line while picking.<br />
<br />
<br />
SEE ALSO SOUND SECTION FOR PINS.<br />
<br />
===Open, Partially Open, or Closed Door at Game Start===<br />
<br />
By default, doors are closed at game start. If you want a door to be already open or partially open then do the following.<br />
<br />
'''Note well: Create all doors in their ''closed'' position. Adjust as follows and they will automatically be at the open position when game starts.'''<br />
<br />
Already Open Rotating Door:<br />
* Select the door.<br />
* Select the entity inspector<br />
* Check ''show inherited properties''<br />
* Select the ''open'' property<br />
* Edit the value to 1 in the input box below and tick the check button<br />
* The door will now be fully open at game start.<br />
<br />
* If you want it only partly open:<br />
* Make sure its ''open'' property is set to 1 as above.<br />
* Right click the entity inspector and select ''add property'' <br />
* Click the + sign on the left of the top line where atdm:mover_door is listed to open the folder. (if atdm:mover_door is not listed then the entity was likely changed from eg, func_static. If so, save the map and reload to update the add property list)<br />
* scroll down, select ''start_rotate'' then click {{ok}}<br />
* This adds it to the property list.<br />
* Now select ''start_rotate'' in the property list.<br />
* Edit the bottom line of the input box ''below'' the properties window to the angle you want in the same form as described in the ''Rotate Direction and Open Angle'' section. So for example, to have a door that has a fully open default ''rotate'' value of 0 90 0 to start only half open you would give it a ''start_rotate'' value of 0 45 0. <br />
* In a similar way add the property ''first_frob_open".<br />
* Set it to 1 and a partly open door should then open fully on the first frob.<br />
* Set it to 0 and a partly open door should close on the first frob.<br />
<br />
<br />
Already Open Sliding Door:<br />
* Select the door.<br />
* Select the entity inspector<br />
* Check ''show inherited properties''<br />
* Select the ''open'' property<br />
* Edit the value to 1 in the input box below and click {{check}} or press {{key-enter}}<br />
* The door will now be fully open at game start.<br />
<br />
* If you want it only partly open:<br />
* Right click the entity inspector and select ''add property'' <br />
* Make sure its ''open'' property is set to 1<br />
* Click the + sign on the left of the top line where atdm:mover_door is listed to open the folder.<br />
* scroll down, select ''start_position'' then click OK. (if atdm:mover_door is not listed then the entity was likely changed from eg, func_static. If so, save the map and reload to update the add property list)<br />
* This adds it to the property list.<br />
* Now select ''start_position'' in the property list.<br />
* Edit the bottom line of the input box ''below'' the properties window to the position you want in the same form as described in the ''Sliding (Translation) Amount and Direction'' section. So for example, to have a door that has a fully open default ''translate'' value of 0 50 0 to start only half open you would give it a ''start_position'' value of 0 25 0.<br />
* In a similar way add the property ''first_frob_open".<br />
* Set it to 1 and a partly open door should then open fully on the first frob.<br />
* Set it to 0 and a partly open door should close on the first frob.<br />
<br />
===Rotation Centre, Pivot, Hinge point===<br />
<br />
The centre of rotation of a door is at the origin point of its entity and the door rotates with reference to the orientation of that origin point, not the world map. See ''Rotate Direction...'' for more about that. This section only deals with the ''position'' of the rotation centre in the door.<br />
<br />
Model Door Centre of Rotation:<br><br />
The centre of rotation of a model door cannot be changed within Dark Radiant. Because a model door rotates around the centre 'spine' of its back edge this will cause clipping (penetration into solid) as in this example (where the door is set to open to 89 degrees for clarity):<BR>[[Image:modelClipping.jpg]]<BR> So care is needed with placement. You will not normally position a door right next to a wall as in the example but against a shallow frame so clipping will barely be noticeable but either way it can be fixed. You can correct it by adding a translation (see ''Sliding (Translation) Directions'') value of half the door width in the direction of the door handle. This will gently move the door out as it rotates to clear any solid on that side as in this diagram:<br><br />
[[Image:DoorClip.jpg]]<br><br />
Half a door width will typically be about 2. Any 'attachments' such as door handles will still synchronize with the door movement whether the door is rotating, sliding, or both.<br />
<br />
<br />
Brush Door Centre of Rotation:<br><br />
The centre of rotation of a brush door ''can'' be changed. The default origin point of a brush is at its centre. Therefore a default rotating brush door will rotate around its centre when you first create it. So, mappers will commonly need to move that rotation point to a corner or even to some other offset position for example, for an openable window using the door function.<br />
<br />
Put simply, to move the rotation point of a brush door you need to move the entity origin relative to the brush(es.)<br />
<br />
Moving the entity origin (centre of rotation) relative to a brush door:<br />
<br />
* Select the brush door<br />
* Select ''Vertices mode'' (default shortcut key is {{key|name=V}} or button on top toolbar 'Select Vertices')<br />
* Drag the door's entity origin to the point where you want the door to rotate. This should be on the corner on the leading edge side (the side to where the door is opening.) to avoid clipping as in this diagram....<br />
[[Image:getCorner.jpg]]<br />
* You should now find that door rotates around that point.<br />
<br />
===Rotate Direction and Open Angle===<br />
<br />
By default, rotating doors open anti-clockwise (viewed from above) by 90 degrees from the start orientation. If you want to change this edit the ''rotate'' property in the entity inspector. Don't confuse this ''rotate'' property with the ''rotation'' property. In the entity inspector remember that to see the inherited rotate property you must check the box 'Show inherited properties'.<br />
<br />
The three values shown in the rotate property are degrees from the closed position around Y Z X ''entity origin axes'' (NOT absolute map axes) and so include any start ''rotation''. So the Z value is the axis vertical to the entity origin. If you tilt a model door over in Dark Radiant then its entity origin tilts too so the Z axis is tilted too (with respect to the world map vertical.) So with a normally opening model door if you lay it flat on its back it will open upwards and not rotate around on the floor. But a brush door must be treated differently...<br />
<br />
If you turn a brush door using the normal Dark Radiant rotate tool or the Transform Dialog (accessed via a shortcut key) then it only turns the brush ''relative'' to the entity. So, because the entity origin is by default aligned with the world map then ''in most cases'' you can regard a brush door as rotating with respect to the world map if you wish. But there will be a problem when you come to rotations that are not around the main Y Z X axes of the map, for instance a drawbridge that lowers down to the south east. You might think you can combine Y Z X values to get the result you want - and this can be done (for south east use 45 45 90) but it is a bit of a kludge and the drawbridge twists eccentrically as it lowers (though it arrives correctly!) So for such cases you need to turn the entity itself so its start position is facing south east. You can then just use 0 0 90 to lower the drawbridge perfectly because its Y axis is now pointing south east. To turn the entity you must type or paste the rotation values in directly because using the Dark Radiant rotation tool or Transform Dialog will only turn the brush not the entity. The values are rather lengthy (south east is 0.707107 0.707107 0 -0.707107 0.707107 0 0 0 1) so probably the easiest way is to create a temporary model door, turn it how you want, then select its rotation property. If you now deselect and re-select your brush door then that property will still be in the entity inspector input box and you need only click the check(tick) box to add it to the brush door. NOTE: ''neither the entity nor the brush will show as turned in Dark Radiant.'' Only the rotation property in the entity inspector will indicate the orientation. Instead of a rotated ''construction'', regard it as a rotation ''instruction'' for when the map is compiled.<br />
<br />
These are the rotate property fields. Remember they are all with reference to the door's entity ''not'' the world map. Since there is no absolute frame of reference I indicate them here as if the entity is aligned with the world map axes...<br />
<br />
* Positive Y = Open clockwise (Dark Radiant grid front view, looking north)<br />
* Negative Y = Open anti-clockwise (Dark Radiant grid front view, looking north)<br />
<br />
* Positive Z = Open anti-clockwise (Dark Radiant grid top view, looking down)<br />
* Negative Z = Open clockwise (Dark Radiant grid top view, looking down)<br />
<br />
* Positive X = Open anti-clockwise (Dark Radiant grid side view, looking west)<br />
* Negative X = Open clockwise (Dark Radiant grid side view, looking west)<br />
<br />
The values are in the range -179 to +180. Positive values give an anti-clockwise opening rotation (looking down from above) and negative values give a clockwise opening rotation. The value 180 is unique in that it continues in an anti-clockwise rotation when closing rather than returning clockwise so might be used if you can think of some object that might need such a motion when frobbed!<br />
<br />
Edit the rotate value by selecting it and using the input box at the bottom and clicking the check(tick) button. That will change the angle the door will open to. Note that the line with the original default of 0 90 0 will still be there but your new entry will be added on a separate line and that is the one that will work in the game. CAUTION: when adjusting later make sure you have your new line selected and not the original! If you do it will appear to change but your first setting will remain unaltered.<br />
<br />
Examples:<br />
* 0 90 0 = Opens anti-clockwise round the entity's 'vertical' to 90 degrees - typical default vertical door.<br />
* 0 0 90 = Lowers a drawbridge from the entity 'vertical' to horizontal.<br />
* 0 0 -45 = Opens clockwise by 45 degrees viewed from the east side. This might suit a skylight in a sloping roof.<br />
<br />
Combinations can be used and also combined with slide motions (see '''Sliding (Translation) Directions''') to produce exotic and useful motions. A door opening against an upward-sloping floor can thus have a ''lifting hinge'' and raise up slightly to clear the floor; a door can rotate towards you and slide back to one side very effectively.<br />
<br />
<br />
===Sliding (Translation) Amount and Direction===<br />
<br />
By default a Dark Mod door will rotate open. For most sliding doors you want to stop them rotating as well as make them slide. You cannot delete (remove) the ''rotate'' property - you have to set the ''rotate'' property to 0 0 0 to stop a door rotating (see ''Rotate Direction and Open Angle''.)<br />
<br />
Now edit the ''translate'' property value by selecting it (remember to have inherited properties box checked) and using the input box at the bottom and clicking the check(tick) button. That will change the distance the door will slide to. Note that the line with the original default of 0 0 0 will still be there but your new entry will be added on a separate line and that is the one that will work in the game. CAUTION: when adjusting later make sure you have your new line selected and not the original! If you do it will appear to change but your first setting will remain unaltered.<br />
<br />
Typically (but not always) you will want your sliding door to slide the width of the door. The three values in the translate property by default are 0 0 0 and are X Y Z ''absolute map'' values (irrespective of door orientation) where:<br />
<br />
* Positive X = Slide East (Right side of Dark Radiant grid in top view)<br />
* Negative X = Slide West (Left side of Dark Radiant grid in top view)<br />
* Positive Y = Slide North (top of Dark Radiant grid in top view)<br />
* Negative Y = Slide South (bottom of Dark Radiant grid in top view)<br />
* Positive Z = Slide Up (Top of Dark Radiant grid in side views)<br />
* Negative Z = Slide Down (Bottom of Dark Radiant grid in side views)<br />
<br />
So for a 50 unit wide door you want to slide fully to the east you would use 50 0 0 for the translate property values. A 100 unit portcullis sliding vertically up would need 0 0 100 to be fully raised.<br />
<br />
=== Doors Collision/Push Behaviour ===<br />
Doors are pushing all entities by default, except for the player. Doors will also stop moving when anything blocks their movement. However, this default behaviour can be changed by setting the according spawnargs:<br />
<br />
Set '''push_player''' to '''1''' to let the player be pushed by this door:<br />
"push_player" "1" // Push the player too (default is off)<br />
<br />
By default '''stop_when_blocked''' is set to 1 and if a door is blocked by an entity then even if the entity is removed afterwards, the door stays still. The next frob will close the door.<br />
<br />
Set '''stop_when_blocked''' to '''0''' to prevent the door from ending the opening sequence when anything blocks its way. It will still pause - but continue to open if the block is removed.<br />
"stop_when_blocked" "0" // door keeps moving after being blocked (default is off)<br />
With this setting, doors will still stop at blocking entities (the player, for instance), but will continue to move when the entity clears the way.<br />
<br />
There is another spawnarg which stops a door pushing a moveable. Apply this to the ''moveable'' not the door...<br />
<br />
"notPushable" "1"<br />
<br />
===Sounds and Sound Propagation through Doors and Doorways===<br />
<br />
Sound propagation relies on visportals. For details study [[Sound Propagation: Part 1]] and [[Sound Propagation: Part 2]] as well as [[Visportals]] This tutorial will just cover the relevant sound and sound propagation ''properties'' of doors. If you set the ''show inherited properties'' box in the entity inspector you can see them as described here.<br />
<br />
The sound of doors opening and closing is set in the snd_open and snd_close properties. You can silence them by setting the following properties as shown:<br />
<br />
''snd_open null''<br><br />
''snd_close null''<br />
<br />
Don't just use a dash - as it seems to cause a sound of its own.<br />
<br />
''snd_locked''<br><br />
The sound played when a player tries to open a locked door.<br />
<br />
''snd_unlock string''<br><br />
The sound played when a player unlocks a door.<br />
<br />
''loss_open''<br><br />
Drop in sound volume in dB when going through an open door. (default 1dB)<br />
<br />
''loss_closed''<br><br />
Drop in sound volume in dB when going through a closed door. (default 15dB) You would want to set this very high to block all sound with a thick door but very low for a barred gate for example.<br />
<br />
''loss_double_open''<br><br />
Drop in sound volume in dB when going through double doors when only one is open. (default 1dB)<br />
<br />
There are also various sound properties for lockpicking:<br><br />
''snd_lockpick_pin_1 through 14'' and ''snd_lockpick_pin_success''<br />
<br />
<br />
===Speed of Door Opening and Closing===<br />
<br />
Rotating Door Speed:<br><br />
At the time of writing, the time a rotating door takes to open or close is set in the ''move_time'' property whatever its maximum open angle. So with rotation set at say 150 degrees the door just opens faster than at say 80 degrees. This is likely to be changed to a constant angular velocity so check to see if there a new property added if the following no longer works. The problem is that if an interruptable (see Extra Notes) door is frobbed while in motion it stops; another frob will reverse the motion - so even if the door is only open a crack it will still take the full time to close and vice versa.<br />
<br />
To change the time a rotating door takes to open or close, make sure the door is selected then...<br />
<br />
* Right click the entity inspector and check ''show inherited properties''<br />
* Scroll down, select ''move_time''<br />
* Edit the second line of the input box ''below'' the properties window to the time you want.<br />
* The time is in seconds and decimal fractions can be used.<br />
* The default is 1 second and if set to this then the door opens and closes in one second whatever the maximum open angle, great or small.<br />
<br />
<br />
Sliding Door Speed:<br><br />
The speed of a sliding door is set in the ''translate_speed'' property. To add this, make sure the door is selected then...<br />
<br />
* Right click the entity inspector and check ''show inherited properties''<br />
* Scroll down, select ''translate_speed''<br />
* Edit the second line of the input box ''below'' the properties window to the speed you want.<br />
* The speed is in Dark Radiant grid units per second.<br />
* The default is 0 and if set to this then the door slides open in one second whatever the distance, great or small.<br />
* CAUTION: If you later change the door back to a rotating door then delete the ''translate_speed'' property or ensure it is set to 0 as (at the time of writing but this will be fixed) a bug makes rotating doors open and close instantly. (Note: you can still mix sliding with rotating but check - this bug might only be if ''translate'' is set to 0 0 0)<br />
<br />
===Visportals and Doors===<br />
<br />
A visportal face surrounded by solid at its edges and in contact with a door is closed when the door is closed and enabled when the door is open. In most cases you will place a visportal in contact with a working door unless you can see through the door (such as a true glass door or barred gate.) For full details see [[Visportals]].<br />
<br />
==Auto-Closing/Opening Doors==<br />
Doors that automatically close after being open for some time are easy to setup: Each frobmover entity supports these spawnargs:<br />
<br />
;"auto_close_time":Set this to something >= 0 to let the mover automatically close (again) after this time when being fully opened (measured in seconds). Defaults to -1, which means 'do not autoclose'. The event is also activated when the mover starts at the open position at map start.<br />
;"auto_open_time":"Set this to something >= 0 to let the mover automatically open (again) after this time when being fully closed (measured in seconds). Defaults to -1, which means 'do not autoopen'. The event is also activated when the mover starts at the closed position at map start.<br />
<br />
Old text:<br />
<br />
Note that auto-closing doors and AI closing doors behind them, is very much work in progress at the time of writing, so for now, this is another method that works. Check first if true AI closing of doors is working yet before bothering with this!<br />
<br />
I have one door that I particularly want the AI to close as there is a bit of frame lag inside if not. So I set this up and it works good as an auto-closing door - not as good as a true AI closing door as it will auto close when the player goes through as well but it does look very effective to see AI going through and closing the door behind them. Not tested exhaustively so I don't know if there could be any downside. Here's what to do....<br />
<br />
First a quick summary to make it more clear:<br />
<br />
'''''A trigger_relay is used both as a relay AND carries a stim. We put the trigger_relay with its stim in the path of the open door. The door has a response property. When it opens and contacts the stim its response is to send a signal back to the relay. The relay pauses then closes the door...'''''<br />
<br />
* First, optionally give your door a suitable name like autodoor1, whatever.<br />
* Copy that name to the clipboard.<br />
<br />
Next we need a relay with a delay:<br />
<br />
* Create entity > darkmod > trigger_relay<br />
<br />
* Place it roughly at the position the door will be at when open and to be on the safe side 3/4th of the way to the far end of the door (not the hinge end) to give max distance from the close door.<br />
<br />
* Add the property 'target' and paste in the door name you just copied.<br />
<br />
* Give the relay itself a name, eg, autoDoor_relay_1, and copy that name to the clipboard, you'll need that too in a bit.<br />
<br />
* Add the property delay and the value 3 - this is the delay in seconds before the door will close; 3 seems about right but 2 might be worth a try because to that 3 is added a random value between 0 to 0.5 seconds from the Time Interval we entered for the stim firings.<br />
<br />
* Add the property 'wait' and the value 3. This is the time before it can work again in seconds. If you set it too low then in theory the door might trigger again but in this situation I don't think it's possible. Too long, eg, one minute, and it won't work if the AI goes back through the door before then. If this value is -1 then the whole thing will only work ONCE so might be used for an AI who goes through once, closes it behind him, but you don't want it to be an autodoor thereafter.<br />
<br />
<br />
That's the relay, now we add a stim to it:<br />
<br />
* Still with the trigger relay selected, go to {{menu|Entity|Stim/Response}}<br />
<br />
* Custom stim tab.<br />
<br />
* Click Add stim type, select the new custom stim type you just made at the bottom of the list and type in eg, autoDoorStim at top right in the input box.<br />
<br />
* Click the stim tab and the little drop down arrow against the 'type' selector at bottom left and you should see your new custom stim name. Select it.<br />
<br />
* Select the new autoDoorStim in the list and on the right you need only type in the radius box 15.0 There is quite a lot of room for error. I had it working on 10 and also on 25. The value should be less than the distance to the closed door else it will trigger open! But no so small that the door might not reach it.<br />
<br />
* Select the check box for Time Interval and enter 500 (millisecs.) This is so it doesn't keep firing more frequently than is necessary. This stim will be firing all through your mission whether the door is used or not so if you had dozens of these then maybe it would affect performance. Too big a number and there may be a long delay before the door shuts - but it will be random depending on the next time the stim happens to fire. We'll control the delay we want more precisely later.<br />
<br />
* Click {{ok}} to confirm it.<br />
<br />
<br />
That's the stim set up, now for the response to it which is put on the door....<br />
<br />
* Select the doorm, then use {{menu|Entity|Stim/response}} and select the response tab.<br />
<br />
* Click the little drop down arrow against the 'type' selector at bottom left and you should see your new custom stim name. Select it.<br />
<br />
* Right click in the big ''Response Effects'' box on the bottom right of the panel.<br />
<br />
* Add New Effect and you should get a default 'Activate Response' response added to the list. Double click it.<br />
<br />
* In the Effect selector at the stop select 'Trigger'<br />
<br />
* in the Target box, paste in the name of the relay you copied or you can select it from the list at the little arrow.<br />
<br />
* Leave the Activator box empty.<br />
<br />
* Click {{apply}} and then {{ok}} on the main S & R panel bottom right.<br />
<br />
It should now work. No need to wait for an AI, just frob the door and watch it close itself. If not, check the position of the stim brush is close to where the door stops when open.<br />
<br />
==AI Door management==<br />
<br />
By default AI will open doors and close them behind them. Here are some spawnargs the mapper can use to modify that behaviour:<br />
<br />
;"ai_should_not_handle" :If set to 1, AI will not attempt to handle it and add it to the forbidden areas when closed (so that it doesn't try to path through). They might still walk through the door when it is open though. Useful if you have some special use door that you don't want the AI to operate.<br />
<br />
;"ai_should_not_close" :If set to 1, AI will not close the door behind them unless it obstructs them.<br />
<br />
<br />
To get AI to unlock/relock specific doors there are two methods currently:<br />
<br />
1. add the following spawnarg/value to the AI:<br />
<br />
;"can_unlock1" ''<doorname>''<br />
<br />
'''Do NOT use can_unlock_1.'''<br />
<br />
For additional doors on the same AI use ''can_unlock2 doorname'' etc.<br />
<br />
<br />
2. In the editor position an actual key that works for that door on the AI and also add to the key bind <AIname> and also bindToJoint LeftHips_Dummy (see other joints names elsewhere in wiki.) Currently, if the player pickpockets the key then the AI seeks an alternate route but otherwise does nothing (?) This may be upgraded in the future to better strategies.<br />
<br />
3. There is the possibility in the future of an additional method which would just use special attach spawnargs to make the above easier. The key would spawn at the correct position at game start. Watch this space.<br />
<br />
<br />
'''Door handling positions'''<br />
<br />
It is also possible to set custom door handling positions for the AI. This is especially useful when the standard routine that lets the AI choose their standing positions while opening and closing the door fails, leaving them circling around in front of the door helplessly.<br />
<br />
Place a atdm:door_handling_position entity where you want the AI to stand while opening/closing the door from this side.(it can be found in the movers folder in the entity chooser)<br />
<br />
On the door, you need to set the spawn arg "door_handling_position" "name_of_door_handling_position" You can also place a door handling position on each side of the door, the AI should automatically choose the right one. In this case, you need to set spawn args with "door_handling_position_1" etc and the corresponding names of the door handling position entities on the door.<br />
<br />
The door handling positions can also carry spawn args that define the behaviour of the AI, which are useful for example for doors that can only be openend or locked from one side:<br />
<br />
'''"ai_no_open"''' If set to true, the AI will not try to open the door from this side (but still walk through when the door is already open)<br />
<br />
'''"ai_no_close"''' If set to true, the AI will not attempt to close the door from this side<br />
<br />
'''"ai_no_unlock"''' If set true, the AI will not be able to unlock the door from this side, but still use it when it is not locked.<br />
<br />
'''"ai_no_lock"''' If this is set true, the AI will not lock the door from this side.<br />
<br />
==Doors as Triggers==<br />
<br />
''by Ishtvan & greebo''<br />
<br />
Doors (or any binary frob mover, buttons, levers, etc) now have the option to trigger their target on closing or opening. (For definition purposes, a button is defined as "closed" in the state when it starts out and "open" in the state you press it down to. I know that's a little non-intuitive, but it came from deriving from doors).<br />
<br />
New spawnargs on frob movers:<br />
;"trigger_on_open" :If set to 1, this binary mover will trigger its targets when it starts out completely closed and is opened.<br />
;"trigger_when_opened":If set to 1, this binary mover will trigger its targets when it is completely opened. Code defaults to 0.<br />
;"trigger_on_close":If set to 1, this binary mover will trigger its targets when it completely closes after being open.<br />
<br />
<br />
<br />
==Skins: A Wide Variety of Door Textures==<br />
<br />
This is to remind you that as with many Dark Mod models, there is a wide range of extras skins (textures) available for door models. There are now several basic door entities of different sizes so choose your size first. Then enter the spawnarg: skin with any temporary value. Now select it and click the skin button at the bottom of Dark Radiant's Entity Inspector and you will find a large of range of skin textures from which to select to give you a choice of appearances for your door.<br />
<br />
<br />
<br />
==Extra Notes==<br />
The property ''interruptable'' determines whether a door can be stopped by frobbing while it is opening or closing. So by frobbing then frobbing again, the player can open a door to any position, eg, slightly ajar to peek through.<br />
<br />
''func_darkmod_door'' is no longer used (just in case you come across it in the Dark Mod forums or wiki.) The Doom func_door is still available but for Dark Mod, but <code>atdm:mover_door</code> is the entity to use.<br />
<br />
{{tutorial-editing}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Interleaved_Thinking_optimization&diff=8011Interleaved Thinking optimization2009-04-20T11:24:58Z<p>Angua: </p>
<hr />
<div>This optimization is used to reduce the effect of the AI's thinking routine on game performance. Depending on the distance to the player, AI will only think once in a certain number of frames. This includes the Mind (States and Tasks), path finding and physics. Multiple AI will think on different frames (started randomly). Interleaved thinking is switched off if the AI is in the player's view (it doesn't look good since the animations are not played properly, and AI alertness is reduced)<br />
<br />
The settings can be adjusted for each AI via spawnargs (in the def file or on the entity in the map).<br />
<br />
* '''min_interleave_think_dist:''' If the distance to the player is smaller than this, the AI will think every frame.<br />
* '''max_interleave_think_dist:''' If the distance to the player is larger than this, the AI will only think once in the number of frames given by max_interleave_think_frames. The thinking frequency decreases linearly between min and max dist.<br />
* '''max_interleave_think_frames:''' The AI will only think once in this number of frames if the distance to the player is larger than max_interleave_think_dist. Setting this to 1 will make the AI think every frame.<br />
<br />
'''IMPORTANT!''' Do not set max_interleave_think_frames to high values (above 30). This will lead to path finding and physics problems, the AI might run into a wall and get damaged or even die.<br />
<br />
The settings in the spwan args can be overwritten using [[Cvars]] (for testing only). It is also possible to switch the PVS check off so that AI can also do interleaved thinking while in the player's view.<br />
<br />
{{ai}} {{sdk}} {{editing}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Visual_scan&diff=7118Visual scan2008-09-21T19:56:44Z<p>Angua: </p>
<hr />
<div>This article describes the routine used to detect whether the AI can see the player, and to alert it if this is the case. <br />
<br />
Each frame, a probability check depending on lightgem brightness, player distance and the AI's visual acuity is used to detect whether the AI has spotted the player.<br />
<br />
The base probability, '''clampVal''' is calculated from the light gem value itself. The value should represent the probability to be seen within half a second (so with a clampVal of 0.1, you would be spotted approximately once in 5 seconds).<br />
I used a polynomial function for this, since the AI were not sensitive enough with a linear increase. <br />
Here is it (for the other math freaks):<br />
<br />
clampVal = -0.03 + 0.03 * lgem + 1 * 10^-3 * lgem^2 + 1.3 * 10^-4 * lgem^3 - 1.1 * 10^-5 * lgem^4 + 1.892 * 10^-7 * lgem^5<br />
<br />
(The grey curve shows the probability before tweaking.)<br />
<br />
[[Image:clamp.jpg]]<br />
<br />
The clampVal is scaled with the AI's visual acuity.<br />
<br />
Within the '''clampDistance''', the probability stays constant, and it decreases linearly towards zero at the '''saveDistance'''. Both distances are scaled with the clampVal, so that you have to be really close to the AI in ambient light to be spotted at all. The maximum values for full brightness are given by the Cvars "tdm_ai_sightmin" (default: 11 meters) and "tdm_ai_sightmax" (default: 60 m).<br />
<br />
'''returnVal''' is the resulting probability depending on the player distance. With this probability, a random check is performed each frame whether the AI has spotted the player. If this succeeds, the AI has caught a glance of the player and becomes alerted.<br />
<br />
The alert increase also depends on lightgem brightness, player distance and acuity and is currently between 4 and 13 units (currently hard coded, but will become a spawnarg soon). This means, that an idle AI should go to observant for a single low alert, but into searching if the player was spotted in bright light.<br />
<br />
<br />
For debugging, you can use the [[Cvars|Cvar]]<br />
<br />
'''tdm_ai_visdist_show 1'''<br />
<br />
<br />
<br />
<br />
{{ai}} {{sdk}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Visual_scan&diff=7117Visual scan2008-09-21T19:41:44Z<p>Angua: </p>
<hr />
<div>This article describes the routine used to detect whether the AI can see the player, and to alert it if this is the case. <br />
<br />
Each frame, a probability check depending on lightgem brightness, player distance and the AI's visual acuity is used to detect whether the AI has spotted the player.<br />
<br />
The base probability, '''clampVal''' is calculated from the light gem value itself. The value should represent the probability to be seen within half a second (so with a clampVal of 0.1, you would be spotted approximately once in 5 seconds).<br />
I used a polynomial function for this, since the AI were not sensitive enough with a linear increase. <br />
Here is it (for the other math freaks):<br />
<br />
clampVal = -0.03 + 0.03 * lgem + 1 * 10^-3 * lgem^2 + 1.3 * 10^-4 * lgem^3 - 1.1 * 10^-5 * lgem^4 + 1.892 * 10^-7 * lgem^5<br />
<br />
(The grey curve shows the probability before tweaking.)<br />
<br />
[[Image:clamp.jpg]]<br />
<br />
The clampVal is scaled with the AI's visual acuity.<br />
<br />
Within the '''clampDistance''', the probability stays constant, and it decreases linearly towards zero at the '''saveDistance'''. Both distances are scaled with the clampVal, so that you have to be really close to the AI in ambient light to be spotted at all. The maximum values for full brightness are given by the Cvars "tdm_ai_sightmin" (default: 11 meters) and "tdm_ai_sightmax" (default: 60 m).<br />
<br />
'''returnVal''' is the resulting probability depending on the player distance. With this probability, a random check is performed each frame whether the AI has spotted the player. If this succeeds, the AI has caught a glance of the player and becomes alerted.<br />
<br />
The alert increase also depends on lightgem brightness, player distance and acuity and is currently between 4 and 13 units (currently hard coded, but will become a spawnarg soon). This means, that an idle AI should go to observant for a single low alert, but into searching if the player was spotted in bright light.<br />
<br />
<br />
For debugging, you can use<br />
<br />
'''tdm_ai_visdist_show 1'''<br />
<br />
<br />
<br />
<br />
{{ai}} {{sdk}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Visual_scan&diff=7116Visual scan2008-09-21T19:37:15Z<p>Angua: </p>
<hr />
<div>This article describes the routine used to detect whether the AI can see the player, and to alert it if this is the case. <br />
<br />
Each frame, a probability check depending on lightgem brightness, player distance and the AI's visual acuity is used to detect whether the AI has spotted the player.<br />
<br />
The base probability, '''clampVal''' is calculated from the light gem value itself. The value should represent the probability to be seen within half a second (so with a clampVal of 0.1, you would be spotted approximately once in 5 seconds).<br />
I used a polynomial function for this, since the AI were not sensitive enough with a linear increase. <br />
Here is it (for the other math freaks):<br />
<br />
clampVal = -0.03 + 0.03 * lgem + 1 * 10^-3 * lgem^2 + 1.3 * 10^-4 * lgem^3 - 1.1 * 10^-5 * lgem^4 + 1.892 * 10^-7 * lgem^5<br />
<br />
(The grey curve shows the probability before tweaking.)<br />
<br />
[[Image:clamp.jpg]]<br />
<br />
The clampVal is scaled with the AI's visual acuity.<br />
<br />
Within the '''clampDistance''', the probability stays constant, and it decreases linearly towards zero at the '''saveDistance'''. Both distances are scaled with the clampVal, so that you have to be really close to the AI in ambient light to be spotted at all. The maximum values for full brightness are given by the Cvars "tdm_ai_sightmin" (default: 11 meters) and "tdm_ai_sightmax" (default: 60 m).<br />
<br />
'''returnVal''' is the resulting probability depending on the player distance. With this probability, a random check is performed each frame whether the AI has spotted the player. If this succeeds, the AI has caught a glance of the player and becomes alerted.<br />
<br />
The alert increase also depends on lightgem brightness, player distance and acuity and is currently between 4 and 13 units (currently hard coded, but will become a spawnarg soon). This means, that an idle AI should go to observant for a single low alert, but into searching if the player was spotted in bright light.<br />
<br />
<br />
{{ai}} {{sdk}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=File:Clamp.jpg&diff=7115File:Clamp.jpg2008-09-21T19:30:00Z<p>Angua: uploaded a new version of "Image:Clamp.jpg"</p>
<hr />
<div>Probability for being spotted based on lightgem brightness</div>Anguahttps://wiki.thedarkmod.com/index.php?title=File:Clamp.jpg&diff=6979File:Clamp.jpg2008-09-15T14:27:38Z<p>Angua: uploaded a new version of "Image:Clamp.jpg"</p>
<hr />
<div>Probability for being spotted based on lightgem brightness</div>Anguahttps://wiki.thedarkmod.com/index.php?title=File:Clamp.jpg&diff=6978File:Clamp.jpg2008-09-15T14:26:05Z<p>Angua: uploaded a new version of "Image:Clamp.jpg"</p>
<hr />
<div>Probability for being spotted based on lightgem brightness</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Visual_scan&diff=6444Visual scan2008-05-21T14:16:17Z<p>Angua: </p>
<hr />
<div>This article describes the routine used to detect whether the AI can see the player, and to alert it if this is the case. <br />
<br />
Each frame, a probability check depending on lightgem brightness, player distance and the AI's visual acuity is used to detect whether the AI has spotted the player.<br />
<br />
The base probability, '''clampVal''' is calculated from the light gem value itself. The value should represent the probability to be seen within half a second (so with a clampVal of 0.1, you would be spotted approximately once in 5 seconds).<br />
I used a polynomial function for this, since the AI were not sensitive enough with a linear increase. <br />
Here is it (for the other math freaks):<br />
<br />
clampVal = -0.01 + 0.015 * lgem + 1.8 * 10^-3 * lgem^2 + 1.28 * 10^-4 * lgem^3 - 1.14 * 10^-5 * lgem^4 + 1.93 * 10^-7 * lgem^5<br />
<br />
[[Image:clamp.jpg]]<br />
<br />
The clampVal is scaled with the AI's visual acuity.<br />
<br />
Within the '''clampDistance''', the probability stays constant, and it decreases linearly towards zero at the '''saveDistance'''. Both distances are scaled with the clampVal, so that you have to be really close to the AI in ambient light to be spotted at all. The maximum values for full brightness are given by the Cvars "tdm_ai_sightmin" (default: 11 meters) and "tdm_ai_sightmax" (default: 60 m).<br />
<br />
'''returnVal''' is the resulting probability depending on the player distance. With this probability, a random check is performed each frame whether the AI has spotted the player. If this succeeds, the AI has caught a glance of the player and becomes alerted.<br />
<br />
The alert increase also depends on lightgem brightness, player distance and acuity and is currently between 4 and 10 units (currently hard coded, but will become a spawnarg soon). This means, that an idle AI should go to observant for a single low alert, but into searching if the player was spotted in bright light.<br />
<br />
<br />
{{ai}} {{coding}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Visual_scan&diff=6443Visual scan2008-05-21T14:01:16Z<p>Angua: </p>
<hr />
<div>This article describes the routine used to detect whether the AI can see the player, and to alert it if this is the case. <br />
<br />
Each frame, a probability check depending on lightgem brightness, player distance and the AI's visual acuity is used to detect whether the AI has spotted the player.<br />
<br />
The base probability, '''clampVal''' is calculated from the light gem value itself. The value should represent the probability to be seen within half a second (so with a clampVal of 0.1, you would be spotted approximately once in 5 seconds).<br />
I used a polynomial function for this, since the AI were not sensitive enough with a linear increase. <br />
<br />
[[Image:clamp.jpg]]<br />
<br />
The clampVal is scaled with the AI's visual acuity.<br />
<br />
Within the '''clampDistance''', the probability stays constant, and it decreases linearly towards zero at the '''saveDistance'''. Both distances are scaled with the clampVal, so that you have to be really close to the AI in ambient light to be spotted at all. The maximum values for full brightness are given by the Cvars "tdm_ai_sightmin" (default: 11 meters) and "tdm_ai_sightmax" (default: 60 m).<br />
<br />
'''returnVal''' is the resulting probability depending on the player distance. With this probability, a random check is performed each frame whether the AI has spotted the player. If this succeeds, the AI has caught a glance of the player and becomes alerted.<br />
<br />
The alert increase also depends on lightgem brightness, player distance and acuity and is currently between 4 and 10 units (currently hard coded, but will become a spawnarg soon). This means, that an idle AI should go to observant for a single low alert, but into searching if the player was spotted in bright light.<br />
<br />
<br />
{{ai}} {{coding}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Visual_scan&diff=6442Visual scan2008-05-21T13:58:32Z<p>Angua: </p>
<hr />
<div>This article describes the routine used to detect whether the AI can see the player, and to alert it if this is the case. <br />
<br />
Each frame, a probability check depending on lightgem brightness, player distance and the AI's visual acuity is used to detect whether the AI has spotted the player.<br />
<br />
The base probability, '''clampVal''' is calculated from the light gem value itself. The value should represent the probability to be seen within half a second (so with a clampVal of 0.1, you would be spotted approximately once in 5 seconds).<br />
I used a polynomial function for this, since the AI were not sensitive enough with a linear increase. <br />
[[Image:clamp.jpg]]<br />
<br />
The clampVal is scaled with the AI's visual acuity.<br />
<br />
Within the '''clampDistance''', the probability stays constant, and it decreases linearly towards zero at the '''saveDistance'''. Both distances are scaled with the clampVal, so that you have to be really close to the AI in ambient light to be spotted at all. The maximum values for full brightness are given by the Cvars "tdm_ai_sightmin" (default: 11 meters) and "tdm_ai_sightmax" (default: 60 m).<br />
<br />
'''returnVal''' is the resulting probability depending on the player distance. With this probability, a random check is performed each frame whether the AI has spotted the player. If this succeeds, the AI has caught a glance of the player and becomes alerted.<br />
<br />
The alert increase also depends on lightgem brightness, player distance and acuity and is currently between 4 and 10 units (currently hard coded, but will become a spawnarg soon). This means, that an idle AI should go to observant for a single low alert, but into searching if the player was spotted in bright light.<br />
<br />
<br />
{{ai}} {{coding}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=File:Clamp.jpg&diff=6441File:Clamp.jpg2008-05-21T13:57:15Z<p>Angua: Probability for being spotted based on lightgem brightness</p>
<hr />
<div>Probability for being spotted based on lightgem brightness</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Visual_scan&diff=6440Visual scan2008-05-21T13:55:54Z<p>Angua: </p>
<hr />
<div>This article describes the routine used to detect whether the AI can see the player, and to alert it if this is the case. <br />
<br />
Each frame, a probability check depending on lightgem brightness, player distance and the AI's visual acuity is used to detect whether the AI has spotted the player.<br />
<br />
The base probability, '''clampVal''' is calculated from the light gem value itself. The value should represent the probability to be seen within half a second (so with a clampVal of 0.1, you would be spotted approximately once in 5 seconds).<br />
I used a polynomial function for this, since the AI were not sensitive enough with a linear increase. <br />
<br />
The clampVal is scaled with the AI's visual acuity.<br />
<br />
Within the '''clampDistance''', the probability stays constant, and it decreases linearly towards zero at the '''saveDistance'''. Both distances are scaled with the clampVal, so that you have to be really close to the AI in ambient light to be spotted at all. The maximum values for full brightness are given by the Cvars "tdm_ai_sightmin" (default: 11 meters) and "tdm_ai_sightmax" (default: 60 m).<br />
<br />
'''returnVal''' is the resulting probability depending on the player distance. With this probability, a random check is performed each frame whether the AI has spotted the player. If this succeeds, the AI has caught a glance of the player and becomes alerted.<br />
<br />
The alert increase also depends on lightgem brightness, player distance and acuity and is currently between 4 and 10 units (currently hard coded, but will become a spawnarg soon). This means, that an idle AI should go to observant for a single low alert, but into searching if the player was spotted in bright light.<br />
<br />
<br />
{{ai}} {{coding}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Visual_scan&diff=6439Visual scan2008-05-21T13:29:20Z<p>Angua: </p>
<hr />
<div>This article describes the routine used to detect whether the AI can see the player, and to alert it if this is the case. <br />
<br />
Each frame, a probability check depending on lightgem brightness, player distance and the AI's visual acuity is used to detect whether the AI has spotted the player.<br />
<br />
The base probability, '''clampVal''' is calculated from the light gem value itself. The value should represent the probability to be seen within half a second (so with a clampVal of 0.1, you would be spotted approximately once in 5 seconds).<br />
I used a polynomial function for this, since the AI were not sensitive enough with a linear increase. <br />
The clampVal is scaled with the AI's visual acuity.<br />
<br />
Within the '''clampDistance''', the probability stays constant, and it decreases linearly towards zero at the '''saveDistance'''. Both distances are scaled with the clampVal, so that you have to be really close to the AI in ambient light to be spotted at all. The maximum values for full brightness are given by the Cvars "tdm_ai_sightmin" (default: 11 meters) and "tdm_ai_sightmax" (default: 60 m).<br />
<br />
'''returnVal''' is the resulting probability depending on the player distance. With this probability, a random check is performed each frame whether the AI has spotted the player. If this succeeds, the AI has caught a glance of the player and becomes alerted.<br />
<br />
The alert increase also depends on lightgem brightness, player distance and acuity and is currently between 4 and 10 units (currently hard coded, but will become a spawnarg soon). This means, that an idle AI should go to observant for a single low alert, but into searching if the player was spotted in bright light.<br />
<br />
<br />
{{ai}} {{coding}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Visual_scan&diff=6438Visual scan2008-05-21T13:28:12Z<p>Angua: New page: This article describes the routine used to detect whether the AI can see the player, and to alert it if this is the case. Each frame, a probability check depending on lightgem brightness...</p>
<hr />
<div>This article describes the routine used to detect whether the AI can see the player, and to alert it if this is the case. <br />
<br />
Each frame, a probability check depending on lightgem brightness, player distance and the AI's visual acuity is used to detect whether the AI has spotted the player.<br />
<br />
The base probability, '''clampVal''' is calculated from the light gem value itself. The value should represent the probability to be seen within half a second (so with a clampVal of 0.1, you would be spotted approximately once in 5 seconds).<br />
I used a polynomial function for this, since the AI were not sensitive enough with a linear increase. <br />
The clampVal is scaled with the AI's visual acuity.<br />
<br />
Within the '''clampDistance''', the probability stays constant, and it decreases linearly towards zero at the '''saveDistance'''. Both distances are scaled with the clampVal, so that you have to be really close to the AI in ambient light to be spotted at all. The maximum values for full brightness are given by the Cvars "tdm_ai_sightmin" (default: 11 meters) and "tdm_ai_sightmax" (default: 60 m).<br />
<br />
'''returnVal''' is the resulting probability depending on the player distance. With this probability, a random check is performed each frame whether the AI has spotted the player. If this succeeds, the AI has caught a glance of the player and becomes alerted.<br />
<br />
The alert increase also depends on lightgem brightness, player distance and acuity and is currently between 4 and 10 units (currently hard coded, but will become a spawnarg soon). This means, that an idle AI should go to observant for a single low alert, but into searching if the player was spotted in bright light.</div>Anguahttps://wiki.thedarkmod.com/index.php?title=AI_Documentation&diff=6437AI Documentation2008-05-21T12:59:03Z<p>Angua: /* General Coding */</p>
<hr />
<div>This should be the starting point when trying to learn how the AI code in The Dark Mod is working.<br />
<br />
== General Coding ==<br />
As of November 2007, a new AI coding framework has been introduced to further modularise the AI code. See [[AI Framework]] for more information.<br />
<br />
Here is a small list of tutorials:<br />
* [[Scripting basics]]<br />
* [[Playing AI Animations]]<br />
* [[Interleaved Thinking optimization]]<br />
* [[Visual scan]]<br />
<br />
== AI Variables == <br />
See here for a list of important AI (script) variables and how they behave: [[AI Variables]]<br />
<br />
== Alertness ==<br />
All AI in The Dark Mod can have five distinct levels of alertness, indicated by an Alert Index ranging from 0 to 5:<br />
* Alert Index 0: Idle, not suspicious<br />
* Alert Index 1: Observant<br />
* Alert Index 2: Suspicious<br />
* Alert Index 3: Searching<br />
* Alert Index 4: Agitated Searching<br />
* Alert Index 5: Combat, Chasing Enemy<br />
<br />
Despite these states, the actual alert level of an AI is seamless (internally stored in a float), the current Alert Index is changed when the threshold for a given index is exceeded. These thresholds can be set for each AI in its spawnargs, if a mapper wants to mess with that.<br />
<br />
The thresholds are stored in the AI's member variables (thresh_1 to thresh_5). Idle AI have their alertlevel below thresh_1.<br />
<br />
=== Changing Alertness ===<br />
The Alert Level of any AI must be changed through calling '''idAI::SetAlertLevel''' with no exceptions! Directly manipulating the AI_AlertNum is not ok, because the SetAlertLevel method also keeps the AI_AlertIndex and other stuff in sync. Note that calling SetAlertLevel will most probably trigger an [[AI State]] change in the next frame, unless the current State does not allow it.<br />
<br />
Incoming audio, tactile and visual alerts must go through '''idAI::AlertAI''' without exceptions. This way the probability checks are performed before the call to SetAlertLevel is invoked.<br />
<br />
{{ai}}<br />
[[Category:Coding]]</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Interleaved_Thinking_optimization&diff=6436Interleaved Thinking optimization2008-05-21T08:38:01Z<p>Angua: </p>
<hr />
<div>This optimization is used to reduce the effect of the AI's thinking routine on game performance. Depending on the distance to the player, AI will only think once in a certain number of frames. This includes the Mind (States and Tasks), path finding and physics. Multiply AI will think on different frames (started randomly). Interleaved thinking is switched off if the AI is in the player's view (it doesn't look good since the animations are not played properly, and AI alertness is reduced)<br />
<br />
The settings can be adjusted for each AI via spawnargs (in the def file or on the entity in the map).<br />
<br />
* '''min_interleave_think_dist:''' If the distance to the player is smaller than this, the AI will think every frame.<br />
* '''max_interleave_think_dist:''' If the distance to the player is larger than this, the AI will only think once in the number of frames given by max_interleave_think_frames. The thinking frequency decreases linearly between min and max dist.<br />
* '''max_interleave_think_frames:''' The AI will only think once in this number of frames if the distance to the player is larger than max_interleave_think_dist. Setting this to 1 will make the AI think every frame.<br />
<br />
<br />
'''IMPORTANT!''' Do not set max_interleave_think_frames to high values (above 30). This will lead to path finding and physics problems, the AI might run into a wall and get damaged or even die.<br />
<br />
The settings in the spwan args can be overwritten using [[Cvars]] (for testing). It is also possible to switch the PVS check off so that AI can also do interleaved thinking while in the player's view.<br />
<br />
{{ai}} {{coding}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Cvars_in_The_Dark_Mod&diff=6435Cvars in The Dark Mod2008-05-21T08:34:18Z<p>Angua: /* AI */</p>
<hr />
<div>A complete list of Doom 3 Cvars can be found here: http://www.iddevnet.com/doom3/cvars.php<br />
<br />
This should be a list of Cvars that are currently available in the Dark Mod:<br />
<br />
== Inventory ==<br />
* '''tdm_inv_grouping''' Determines whether or not the user-interface uses inventory grouping. It can be changed on the fly without losing the currently selected item.<br />
:* '''0''' means to use a T1/T2 style interface. '''Previous item''' and '''Next item''' are used to scroll through the entire inventory. An empty slot exists between the last and first items of the inventory. '''Previous group''' and '''Next group''' are not functional.<br />
:* '''1''' means to use inventory groups. '''Previous item''' and '''Next item''' are used to scroll through the items in the current group. An empty slot exists between the last and first items of a group. '''Previous group''' and '''Next group''' are used to scroll through the groups of the current inventory in alphabetical order.<br />
:* '''2''' is default, meaning to use a T1/T2 style interface but sort the inventory by group. Items within a given group retain their position relative to eachother, but all items in the first group exist before all items in the second group, and so on. '''Previous item''' and '''Next item''' are used to scroll through the entire inventory. An empty slot exists between the last and first items of the inventory. '''Previous group''' and '''Next group''' are used to scroll through the groups of the current inventory in alphabetical order.<br />
<br />
== HUD ==<br />
* '''tdm_hud_opacity''' : Controls the opacity of the HUD elements. The range is anywhere from '''0''' to '''1''', where '''0''' makes it totally invisible and '''1''' makes it fully opaque. Defaults to 1.<br />
<br />
== Frobbing ==<br />
* '''tdm_frob_ammo_selects_weapon''' (default is "1"): Set this to 1 to have the weapons automatically selected when the respective arrows are frobbed.<br />
<br />
== AI ==<br />
Useful while mapping/testing/designing<br />
* '''tdm_ai_sight''' set to 0 to make AI blind (default 0.7 at time of this writing)<br />
* '''tdm_ai_sndvol''' set to a low negative value, e.g., -300, to make AI deaf (default 0)<br />
* '''tdm_ai_tact''' set to 0 to remove AI sense of touch (default 20)<br />
* '''tdm_ai_showtasks''' shows the current State and Tasks of the AI (see '''[[AI State]]''' and '''[[AI Task]]''').<br />
* '''tdm_ai_showalert''' shows the current alert index and alert level of the AI.<br />
* '''tdm_ai_show_enemy_visibility''' If set to 1, the visibility of the AI's enemy is drawn (red = obscured or hidden in darkness, green = the opposite)<br />
* '''tdm_ai_search_show''' If >= 1.0, this is the number of milliseconds for which a graphic showing search activity targets will be shown.<br />
* '''tdm_ai_showdoor''' Debug output during door handling. The goal standing positions for opening and closing the door will be displayed. At the side of the door where it swings towards, a test with different clipmodel positions is performed to detect whether the AI can stand at this position. A green box indicates that the AI can stand there, while a red box shows that something is in the way. Additionally, the current door handling state of the AI (e.g. MovingToFrontPos, OpeningDoor...) is shown. <br />
* '''tdm_ai_showelevator''' Debug output during operating elevators.<br />
* '''tdm_ai_showanimstate''' Shows the current anim states of the anim channels torso, legs and head, as well as their wait states.<br />
* '''tdm_ai_showbark''' Shows the name of the bark when the AI starts barking (the name in the def, not the sound shader or sound file)<br />
* '''tdm_ai_showdest''' If set to true, an arrow is drawn from every AI to its intended pathing destination.<br />
* '''tdm_ai_showgoalpos''' If set to true, the current goalpos (seekpos) is drawn in the world (!= move destination). The goalpos is used to lead the AI e.g. through door ways and around obstacles towards their pathing destination.<br />
* '''tdm_ai_showAASarea''' Shows the number and boundaries of the AAS area the AI is currently in.<br />
* '''tdm_ai_opt_interleavethinkmindist''' If nonzero, this will overwrite the minimum distance to the player where the [[Interleaved Thinking optimization]] will start. Set to 0 to switch the cvar off and use the spawnarg.<br />
* '''tdm_ai_opt_interleavethinkmaxdist''' If nonzero, this will be the distance where all AI will only think once in the number of frames specified by think_frames. Thinking frequency decreases linearly between min and max distance. Setting this to 0 will switch the cvar off and use the spawn arg value.<br />
* '''tdm_ai_opt_interleavethinkframes''' If nonzero, all AI will only think once in this number of frames if their distance to the player is larger than the max dist. Set to 1 to let all AI think every frame. Set to 0 to use the settings in the spawn arg.<br />
* '''tdm_ai_opt_interleavethinkskipPVS''' Set to 1 to skip the PVS check for interleaved thinking, so AI will also do interlaved thinking when in the player's view.<br />
<br />
<br />
<br />
<br />
* [[AI Attachment Ingame Editing]]<br />
<br />
== Attachment related ==<br />
The following attachment commands must be run while looking at the AI you want to modify, with nothing obstructing your view. I could have made people type in the full name of the AI, but I'd figure we'd see how it works when looking at them. Also, these are meant to be run after you have initially placed the attachments in the def file / spawnArgs of the AI. This step is still done the same as before.<br />
<br />
* '''tdm_attach_print:''' Print the attachment info for the given attachment on the AI you are looking at.<br />
* Usage: tdm_attach_print <attachment index><br />
<br />
* '''tdm_attach_offset''': Set the vector offset (x y z) for an attachment on an AI you are looking at.<br />
* Usage: tdm_attach_offset <attachment index> <x> <y> <z><br />
<br />
* '''tdm_attach_rot''': Set the rotation (pitch yaw roll) for an attachment on an AI you are looking at.<br />
* Usage: tdm_attach_rot <atachment index> <pitch> <yaw> <roll> (NOTE: Rotation is applied before translation, angles are relative to the joint orientation)<br />
<br />
* '''tdm_attach_joint''': Set the attachment joint name for an attachment on an AI you are looking at.<br />
Usage: tdm_attach_joint <attachment index> <string name of joint><br />
<br />
{{scripting}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Pathfinding&diff=6434Pathfinding2008-05-21T08:20:22Z<p>Angua: /* Introduction */</p>
<hr />
<div>''Written by Fidcal''<br />
<br />
<br />
==Introduction==<br />
<br />
This tutorial covers AI pathfinding. By 'AI' is meant any non-player character in the game such as a guard, spider, belcher, etc.<br />
<br />
Plain worldspawn brush terrain (not assigned to entities) is ''collidable'' and also correctly affects pathfinding so AI 'recognize' it either as a barrier to avoid or as a surface on which they can walk. But all patches as well as brushes and models that ''are'' assigned to entities are not recognized by AI as a barrier and they will walk mindlessly forever against such obstacles unless diverted. Nor can they walk over their surface (although the player can.) This is because pathfinding does not take such surfaces into account so will not guide AI around or over them. Yet AI will ''collide'' with them so an AI may try to walk right through a model pillar but refuse to walk over a solid bridge made of static entity brush. This can be put to good use (see ''Preventing and Reducing Pathfinding in selected locations'') but first we shall look at assisting pathfinding...<br />
<br />
==Enabling and Improving Pathfinding in Select Locations==<br />
<br />
The mappers' most important AI pathfinding control is ''monster_clip'' - it is essential in good map building. ''monster_clip'' is an '''invisible''' material used to guide AI around obstacles and over surfaces they otherwise could not traverse. It is not applied directly to existing terrain but placed invisibly around it ''on its own brush''.<br />
<br />
<br />
''monster_clip'' is a texture; find it in the entity inspector under:<br />
<br />
Media > textures > common > monster_clip<br />
<br />
* It must ONLY be applied to a worldspawn brush<br />
* It must NOT be applied to an entity.<br />
* It must be applied to ALL surfaces of the brush.<br />
<br />
The ''monster_clip''-textured '''brush''' is then placed around an entity brush or model to either guide AI away from it or let them walk upon it. It can also be used on its own as an invisible collidable vertical barrier or as an invisible surface to walk upon.<br />
<br />
Although substantial to the AI, ''monster_clip'' is completely invisible and intangible to the player so the player can pass right through it and be unsupported by it. For an invisible barrier or bridge for the player (but not to AI) use ''player_clip'' (also in textures > common.) ''player_clip'' is also useful to cover areas where the player might tend to get stuck.<br />
<br />
<br />
==''monster_clip'' : Vertical Barriers to AI Pathfinding==<br />
<br />
All entity-based terrain and models that lie in the path of AI should be surrounded with a brush wholly textured with ''monster_clip'' or the AI are likely to just blunder into them. They might slide off if there is an angle but they are just as likely to get stuck walking blindly against such a barrier forever. Examples are pillars, statues, railings, anything that is assigned to an entity and is not a plain worldspawn brush should be considered. This does not apply to everything wholesale; anything that will not be in the path of AI should not be surrounded by monster_clip or it will make pathfinding more complex than it needs to be (see ''Preventing and Reducing Pathfinding in Select Locations''.)<br />
<br />
''monster_clip'' brushes around vertical barriers should fully surround them or they might not work properly. In the case of irregular shapes then extend the ''monster_clip'' brush to include the outermost protrusions. In fact in some cases you might wish to be extra generous and make the ''monster_clip'' signficantly bigger if you want the AI to steer well clear for any reason.<br />
<br />
''monster_clip'' brushes can also be used completely on their own as invisible barriers to obstruct or divert AI for whatever reason you wish though obviously you need to keep in mind how the AI's behaviour will look to the player. Remember, the player can move freely through these invisible barriers.<br />
<br />
<br />
==''monster_clip'' : Adding AI pathfinding to Horizontal Surfaces==<br />
<br />
To enable AI to move over horizontal entity surfaces - whether brush or model - you need to surround the object with ''monster_clip or the AI will refuse to go there.<br />
<br />
* The ''monster_clip'' brush should vertically surround the object ''but no more than 16 units above and below'' else they may fail to pathfind over it.<br />
* When walking over a ''monster_clip'' brush surface, AI may stray up to around 18 units out of the 'corridor' of ''monster_clip''. It may be that the edge is calculated for the centre of the AI and not its outer width. For this reason you should reduce the horizontal width by around 18 to keep the AI pathfinding away from the edges where appropriate. For example on a bridge without side rails or walls, if an AI is to turn left or right at the end it will likely move over to one side or other of the bridge as it walks across and is likely to have one leg over the edge! By reducing the ''monster_clip'' width you will keep the AI in a corridor down the middle. If there were a side rail or wall of course then that would have its own ''monster_clip'' so that would keep them on the straight and narrow.<br />
* AI walking over a lone ''monster_clip'' brush that has no entity core will sink into it by about 28 units. This means that if you make an invisible AI-only bridge of ''monster_clip'' then it needs to be 28 units higher than where you want the AI's feet to touch. So a channel with side walls with top surfaces at 100 will need a bridge whose top surface is at 128 in order for the AI to walk smoothly across flush with the side walls. Because 14 to 16 is the maximum step height for an AI you will need a short step of ''monster_clip'' at the entrance and exit for the AI to get on. So this step might be 14 units high but can and should be very shallow - even one unit deep is enough for the AI to pass smoothly on to the main bridge.<br />
<br />
<br />
<br />
==Preventing and Reducing Pathfinding Complexity in Select Locations==<br />
<br />
In areas where there are a great many entity surfaces at about the same level for the AI to walk upon then one large ''monster_clip'' brush can be exended around the lot (see all about ''monster_clip'' in the ''Enabling and Improving Pathfinding in Select Locations'' section.) This will simplify pathfinding and make it more efficient.<br />
<br />
AI will refuse to move over models and brushes assigned to entities unless surrounded by a ''monster_clip'' brush so this is a good method of preventing and reducing pathfinding where needed. This reduces pathfinding complexity and stops AI stepping up on to places such as skirting boards (baseboards.) So...<br />
<br />
Avoid using plain worldspawn brushwork but instead assign them to func_static or some other entity if that is appropriate on...<br />
<br />
* Any area out of reach of AI such as rooftops, balconies, ledges, etc. and especially steep slopes as these can generate complex pathfinding.<br />
* Areas that AI should not or will not walk on such as shallow building trim and decoration, etc.<br />
* And do '''not''' surround them with ''monster_clip'' brushes.<br />
<br />
<br />
==Steep Steps, Slopes, and Extreme Pathfinding!==<br />
<br />
The maximum slope for an AI is approximately 40 degrees from the horizontal but varies upon the situation and the AI. The maximum step height for AI and player is 16 though some AI cannot step up over 14 and perhaps less. But the minimum depth from front to back of a step is only 1 and this can be used to get extreme slopes and very steep steps - even near vertical walls! So, by making a flight of steps each 16 units higher but making each alternate one only one unit deep the overall stair is very steep. The shallow step is near invisible especially if it falls on a join in the texture and anyway it can be made invisible with texture > common > nodrawsolid. Yet AI can step up both this shallow step and the normal step in one convincing motion so this is useful for getting very steep steps where needed. The player can walk up these too with ease and without mantling or jumping.<br />
<br />
Taking the above method to great extremes, once can have the entire stair made with shallow steps no deeper than one unit and this looks like a vertical wall. If made invisible it could really be placed against a visible vertical wall if needed. Both AI and the player will shoot up these extreme steps effortlessly. This is not so natural so not easy to think of an application but mappers are very imaginative and no doubt will use it here and there! Most particularly, keep this shallow step idea in mind when you want the player to cross very rough terrain without struggling or getting stuck. The occasional hidden step here and there and the player can scamper over a boulder field or rough debris without having to keep stopping except where mantling makes better sense.<br />
<br />
One caveat, I set up some ladder brushes as extreme steps. The AI went up and down the ladder (albeit virtually one huge jump with no animation) BUT pathfinding went strange in another part of the mission. Not conclusive but watch for that. (If you try the ladder thing, when you have made the steps, then tilt the whole lot forward so the steps still form a vertical but jagged wall.)<br />
<br />
With all the above, complexity of pathfinding should be kept in mind but mapping is often about balancing the advantage of one thing over another and each situation must be evaluated on its own merits.<br />
<br />
==AI Pathfinding around dynamic obstacles like dropped crates==<br />
<br />
There is code for handling pathfinding around dynamic obstacles (such as moveables, crates, etc.) so there should be no need for the mapper to be concerned with those as AI should automatically avoid them.<br />
<br />
<br />
==Viewing Pathfinding==<br />
<br />
You can view where pathfinding is enabled in-game by binding _impulse27 to a key and pressing it in game. You can do this in the console as a temporary measure or bind it permanently in doomconfig.cfg, eg, to bind it to the keypad asterisk key...<br />
<br />
bind "KP_STAR" "_impulse27"<br />
<br />
When you press the key then the pathfinding areas are shown in wireframe. This is temporary and the display will time out after a few seconds. It also changes colour but the signifcance of the colours I do not know.<br />
<br />
==Why ''func_static'' Brushes Anyway?==<br />
<br />
If you need to surround static entity brushes with separate ''monster_clip'' brushes for AI pathfinding then why not just leave them as plain worldspawn brushes?<br />
<br />
Often you do, but if you do convert a brush to func_static...<br />
<br />
* You can add the property noshadows = 1 so that it doesn't cast shadows, improving frame rates. <br />
* It avoids creation of millions of polys in certain situations where the engine converts a brush into loads.<br />
* It reduces pathfinding complexity (see ''Preventing and Reducing Pathfinding Complexity in Select Locations'')<br />
<br />
<br />
[[Category:Editing]]<br />
[[Category:Tutorial]]</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Interleaved_Thinking_optimization&diff=6429Interleaved Thinking optimization2008-05-20T15:18:49Z<p>Angua: </p>
<hr />
<div>This optimization is used to reduce the effect of the AI's thinking routine on game performance. Depending on the distance to the player, AI will only think once in a certain number of frames. This includes the Mind (States and Tasks), path finding and physics. Multiply AI will think on different frames (started randomly). Interleaved thinking is switched off if the AI is in the player's view (it doesn't look good since the animations are not played properly, and AI alertness is reduced)<br />
<br />
The settings can be adjusted for each AI via spawnargs.<br />
<br />
* '''min_interleave_think_dist:''' If the distance to the player is smaller than this, the AI will think every frame.<br />
* '''max_interleave_think_dist:''' If the distance to the player is larger than this, the AI will only think once in the number of frames given by max_interleave_think_frames. The thinking frequency decreases linearly between min and max dist.<br />
* '''max_interleave_think_frames:''' The AI will only think once in this number of frames if the distance to the player is larger than max_interleave_think_dist. Setting this to 1 will make the AI think every frame.<br />
<br />
<br />
'''IMPORTANT!''' Do not set max_interleave_think_frames to high values (above 30). This will lead to path finding and physics problems, the AI might run into a wall and get damaged or even die.<br />
<br />
The settings can be overwritten using cvars (for testing).</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Interleaved_Thinking_optimization&diff=6428Interleaved Thinking optimization2008-05-20T15:15:27Z<p>Angua: </p>
<hr />
<div>This optimization is used to reduce the effect of the AI's thinking routine on game performance. Depending on the distance to the player, AI will only think once in a certain number of frames. This includes the Mind (States and Tasks), path finding and physics. Multiply AI will think on different frames (started randomly). Interleaved thinking is switched off if the AI is in the player's view (it doesn't look good since the animations are not played properly)<br />
<br />
The settings can be adjusted for each AI via spawnargs.<br />
<br />
* '''min_interleave_think_dist:''' If the distance to the player is smaller than this, the AI will think every frame.<br />
* '''max_interleave_think_dist:''' If the distance to the player is larger than this, the AI will only think once in the number of frames given by max_interleave_think_frames. The thinking frequency decreases linearly between min and max dist.<br />
* '''max_interleave_think_frames:''' The AI will only think once in this number of frames if the distance to the player is larger than max_interleave_think_dist. Setting this to 1 will make the AI think every frame.<br />
<br />
<br />
'''IMPORTANT!''' Do not set max_interleave_think_frames to high values (above 30). This will lead to path finding and physics problems, the AI might run into a wall and get damaged or even die.</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Interleaved_Thinking_optimization&diff=6427Interleaved Thinking optimization2008-05-20T15:02:52Z<p>Angua: </p>
<hr />
<div>This optimization is used to reduce the effect of the AI's thinking routine on game performance. Depending on the distance to the player and if they are in the player's view, AI will only think once in a certain number of frames. This includes the Mind (States and Tasks), path finding and physics. <br />
<br />
The settings for this can be adjusted for each AI via spawnargs.<br />
<br />
* '''max_interleave_think_frames'''<br />
* '''min_interleave_think_dist'''<br />
* '''max_interleave_think_dist'''</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Interleaved_Thinking_optimization&diff=6426Interleaved Thinking optimization2008-05-20T14:59:41Z<p>Angua: New page: This optimization is used to reduce the effect of the AI's thinking routine on game performance. Depending on the distance to the player and if they are in the player's view, AI will only ...</p>
<hr />
<div>This optimization is used to reduce the effect of the AI's thinking routine on game performance. Depending on the distance to the player and if they are in the player's view, AI will only think once in a certain number of frames. This includes the Mind (States and Tasks), path finding and physics. <br />
<br />
The settings for this can be adjusted for each AI via spawnargs.</div>Anguahttps://wiki.thedarkmod.com/index.php?title=AI_Documentation&diff=6425AI Documentation2008-05-20T14:53:15Z<p>Angua: /* General Coding */</p>
<hr />
<div>This should be the starting point when trying to learn how the AI code in The Dark Mod is working.<br />
<br />
== General Coding ==<br />
As of November 2007, a new AI coding framework has been introduced to further modularise the AI code. See [[AI Framework]] for more information.<br />
<br />
Here is a small list of tutorials:<br />
* [[Scripting basics]]<br />
* [[Playing AI Animations]]<br />
* [[Interleaved Thinking optimization]]<br />
<br />
== AI Variables == <br />
See here for a list of important AI (script) variables and how they behave: [[AI Variables]]<br />
<br />
== Alertness ==<br />
All AI in The Dark Mod can have five distinct levels of alertness, indicated by an Alert Index ranging from 0 to 5:<br />
* Alert Index 0: Idle, not suspicious<br />
* Alert Index 1: Observant<br />
* Alert Index 2: Suspicious<br />
* Alert Index 3: Searching<br />
* Alert Index 4: Agitated Searching<br />
* Alert Index 5: Combat, Chasing Enemy<br />
<br />
Despite these states, the actual alert level of an AI is seamless (internally stored in a float), the current Alert Index is changed when the threshold for a given index is exceeded. These thresholds can be set for each AI in its spawnargs, if a mapper wants to mess with that.<br />
<br />
The thresholds are stored in the AI's member variables (thresh_1 to thresh_5). Idle AI have their alertlevel below thresh_1.<br />
<br />
=== Changing Alertness ===<br />
The Alert Level of any AI must be changed through calling '''idAI::SetAlertLevel''' with no exceptions! Directly manipulating the AI_AlertNum is not ok, because the SetAlertLevel method also keeps the AI_AlertIndex and other stuff in sync. Note that calling SetAlertLevel will most probably trigger an [[AI State]] change in the next frame, unless the current State does not allow it.<br />
<br />
Incoming audio, tactile and visual alerts must go through '''idAI::AlertAI''' without exceptions. This way the probability checks are performed before the call to SetAlertLevel is invoked.<br />
<br />
{{ai}}<br />
[[Category:Coding]]</div>Anguahttps://wiki.thedarkmod.com/index.php?title=AI_Documentation&diff=6424AI Documentation2008-05-20T14:47:06Z<p>Angua: /* Alertness */</p>
<hr />
<div>This should be the starting point when trying to learn how the AI code in The Dark Mod is working.<br />
<br />
== General Coding ==<br />
As of November 2007, a new AI coding framework has been introduced to further modularise the AI code. See [[AI Framework]] for more information.<br />
<br />
Here is a small list of tutorials:<br />
* [[Scripting basics]]<br />
* [[Playing AI Animations]]<br />
<br />
== AI Variables == <br />
See here for a list of important AI (script) variables and how they behave: [[AI Variables]]<br />
<br />
== Alertness ==<br />
All AI in The Dark Mod can have five distinct levels of alertness, indicated by an Alert Index ranging from 0 to 5:<br />
* Alert Index 0: Idle, not suspicious<br />
* Alert Index 1: Observant<br />
* Alert Index 2: Suspicious<br />
* Alert Index 3: Searching<br />
* Alert Index 4: Agitated Searching<br />
* Alert Index 5: Combat, Chasing Enemy<br />
<br />
Despite these states, the actual alert level of an AI is seamless (internally stored in a float), the current Alert Index is changed when the threshold for a given index is exceeded. These thresholds can be set for each AI in its spawnargs, if a mapper wants to mess with that.<br />
<br />
The thresholds are stored in the AI's member variables (thresh_1 to thresh_5). Idle AI have their alertlevel below thresh_1.<br />
<br />
=== Changing Alertness ===<br />
The Alert Level of any AI must be changed through calling '''idAI::SetAlertLevel''' with no exceptions! Directly manipulating the AI_AlertNum is not ok, because the SetAlertLevel method also keeps the AI_AlertIndex and other stuff in sync. Note that calling SetAlertLevel will most probably trigger an [[AI State]] change in the next frame, unless the current State does not allow it.<br />
<br />
Incoming audio, tactile and visual alerts must go through '''idAI::AlertAI''' without exceptions. This way the probability checks are performed before the call to SetAlertLevel is invoked.<br />
<br />
{{ai}}<br />
[[Category:Coding]]</div>Anguahttps://wiki.thedarkmod.com/index.php?title=AI_Variables&diff=6423AI Variables2008-05-20T14:45:26Z<p>Angua: /* AI_AlertIndex (scriptFloat) */</p>
<hr />
<div>The AI header is full of variables and it's hard to keep track of what variable is serving which purpose and how often they are updated (and by whom). This list an attempt of listing the most important ones.<br />
<br />
== AI_AlertNum (scriptFloat) ==<br />
This is central variable controlling the AI behaviour. AI_AlertNum can be read directly, but write access must be routed through the '''idAI::SetAlertLevel''' accessor. <br />
<br />
The AI_AlertNum is a floating number representing the current alertness of the AI. Incoming alerts cause the value to increase, long timespans without new alerts let the alertnum decrease. Upon exceeding or falling below certain ''thresholds'', the AI is switching its [[#AI_AlertIndex|AI_AlertIndex]].<br />
<br />
Setting the AI_AlertNum via SetAlertLevel also updates the AI_AlertIndex scriptFloat (see below).<br />
<br />
== AI_AlertIndex (scriptFloat) ==<br />
The AI_AlertIndex is always in sync with the [[#AI_AlertNum|AI_AlertNum]]. Can be queried directly, but '''write access is not allowed''', this must happen through '''idAI::SetAlertLevel''', by whom it is kept up to date.<br />
<br />
An AlertIndex of 0 represents the IdleState, the highest AlertIndex is 5 (CombatState). <br />
This variable is monitored by the [[AI State|Backbone States]], which trigger a State Switch as soon as the AI_AlertIndex is changing (e.g. from IdleState to ObservantState).<br />
<br />
{{ai}}<br />
[[Category:Coding]]</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Cvars_in_The_Dark_Mod&diff=6422Cvars in The Dark Mod2008-05-20T14:35:44Z<p>Angua: /* AI */</p>
<hr />
<div>A complete list of Doom 3 Cvars can be found here: http://www.iddevnet.com/doom3/cvars.php<br />
<br />
This should be a list of Cvars that are currently available in the Dark Mod:<br />
<br />
== Inventory ==<br />
* '''tdm_inv_grouping''' Determines whether or not the user-interface uses inventory grouping. It can be changed on the fly without losing the currently selected item.<br />
:* '''0''' means to use a T1/T2 style interface. '''Previous item''' and '''Next item''' are used to scroll through the entire inventory. An empty slot exists between the last and first items of the inventory. '''Previous group''' and '''Next group''' are not functional.<br />
:* '''1''' means to use inventory groups. '''Previous item''' and '''Next item''' are used to scroll through the items in the current group. An empty slot exists between the last and first items of a group. '''Previous group''' and '''Next group''' are used to scroll through the groups of the current inventory in alphabetical order.<br />
:* '''2''' is default, meaning to use a T1/T2 style interface but sort the inventory by group. Items within a given group retain their position relative to eachother, but all items in the first group exist before all items in the second group, and so on. '''Previous item''' and '''Next item''' are used to scroll through the entire inventory. An empty slot exists between the last and first items of the inventory. '''Previous group''' and '''Next group''' are used to scroll through the groups of the current inventory in alphabetical order.<br />
<br />
== HUD ==<br />
* '''tdm_hud_opacity''' : Controls the opacity of the HUD elements. The range is anywhere from '''0''' to '''1''', where '''0''' makes it totally invisible and '''1''' makes it fully opaque. Defaults to 1.<br />
<br />
== Frobbing ==<br />
* '''tdm_frob_ammo_selects_weapon''' (default is "1"): Set this to 1 to have the weapons automatically selected when the respective arrows are frobbed.<br />
<br />
== AI ==<br />
Useful while mapping/testing/designing<br />
* '''tdm_ai_sight''' set to 0 to make AI blind (default 0.7 at time of this writing)<br />
* '''tdm_ai_sndvol''' set to a low negative value, e.g., -300, to make AI deaf (default 0)<br />
* '''tdm_ai_tact''' set to 0 to remove AI sense of touch (default 20)<br />
* '''tdm_ai_showtasks''' shows the current State and Tasks of the AI (see '''[[AI State]]''' and '''[[AI Task]]''').<br />
* '''tdm_ai_showalert''' shows the current alert index and alert level of the AI.<br />
* '''tdm_ai_show_enemy_visibility''' If set to 1, the visibility of the AI's enemy is drawn (red = obscured or hidden in darkness, green = the opposite)<br />
* '''tdm_ai_search_show''' If >= 1.0, this is the number of milliseconds for which a graphic showing search activity targets will be shown.<br />
* '''tdm_ai_showdoor''' Debug output during door handling. The goal standing positions for opening and closing the door will be displayed. At the side of the door where it swings towards, a test with different clipmodel positions is performed to detect whether the AI can stand at this position. A green box indicates that the AI can stand there, while a red box shows that something is in the way. Additionally, the current door handling state of the AI (e.g. MovingToFrontPos, OpeningDoor...) is shown. <br />
* '''tdm_ai_showelevator''' Debug output during operating elevators.<br />
* '''tdm_ai_showanimstate''' Shows the current anim states of the anim channels torso, legs and head, as well as their wait states.<br />
* '''tdm_ai_showbark''' Shows the name of the bark when the AI starts barking (the name in the def, not the sound shader or sound file)<br />
* '''tdm_ai_showdest''' If set to true, an arrow is drawn from every AI to its intended pathing destination.<br />
* '''tdm_ai_showgoalpos''' If set to true, the current goalpos (seekpos) is drawn in the world (!= move destination). The goalpos is used to lead the AI e.g. through door ways and around obstacles towards their pathing destination.<br />
* '''tdm_ai_showAASarea''' Shows the number and boundaries of the AAS area the AI is currently in.<br />
<br />
<br />
* [[AI Attachment Ingame Editing]]<br />
<br />
== Attachment related ==<br />
The following attachment commands must be run while looking at the AI you want to modify, with nothing obstructing your view. I could have made people type in the full name of the AI, but I'd figure we'd see how it works when looking at them. Also, these are meant to be run after you have initially placed the attachments in the def file / spawnArgs of the AI. This step is still done the same as before.<br />
<br />
* '''tdm_attach_print:''' Print the attachment info for the given attachment on the AI you are looking at.<br />
* Usage: tdm_attach_print <attachment index><br />
<br />
* '''tdm_attach_offset''': Set the vector offset (x y z) for an attachment on an AI you are looking at.<br />
* Usage: tdm_attach_offset <attachment index> <x> <y> <z><br />
<br />
* '''tdm_attach_rot''': Set the rotation (pitch yaw roll) for an attachment on an AI you are looking at.<br />
* Usage: tdm_attach_rot <atachment index> <pitch> <yaw> <roll> (NOTE: Rotation is applied before translation, angles are relative to the joint orientation)<br />
<br />
* '''tdm_attach_joint''': Set the attachment joint name for an attachment on an AI you are looking at.<br />
Usage: tdm_attach_joint <attachment index> <string name of joint><br />
<br />
{{scripting}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Currently_supported_Path_Entities&diff=6395Currently supported Path Entities2008-05-09T10:58:00Z<p>Angua: /* Supported */</p>
<hr />
<div>{{Original_Reference|Ishtvan|3006}}<br />
<br />
Path entities are how you set up AI patrols, AI's turning in place, AI's waiting at a particular point for a while before moving on, AI's randomly switching between two patrol routes, and all combinations of those things.<br />
<br />
The following path_* entities should work, but have not been extensively tested:<br />
<br />
== Supported ==<br />
* '''path_corner''' (this one's been tested)<br />
* '''path_anim''' (plays an anim once when the AI gets to this point in space, then goes on to the next path entity when the anim is done playing)<br />
* '''path_cycleanim''' (stays in place and loops an anim, either for a specified amount of time or until triggered)<br />
* '''path_lookat''' (for the next ''wait'' seconds, turn head to look at the entity given by the ''focus'' spawnarg (defaults to looking at the path_lookat entity itself). Immediately keep moving to next path_* in sequence.)<br />
* '''path_turn''' (turns in place)<br />
* '''path_wait''' ( waits, standing completely motionless at a given place for a given amount of time, then moves to next path_* ) - (tested OK - Fidcal)<br />
* '''path_waitfortrigger''' ( waits at a given place until triggered, then moves to next path_* )<br />
* '''path_hide''' (deactivates and stops rendering the AI)<br />
* '''path_show''' (starts rendering the AI)<br />
* '''path_attack''' (Used to script AI attacking a particular enemy, for scripted sequences I guess. AI will continue on to the next path entity if it kills the enemy)<br />
* '''path_interact''' This lets the AI interact with an entity (for example a button) in a similar way to frobbing. This will only work for buttons etc, but not for inventory items and moevables. The AI will stop and look at the entiy while interacting, but not walk to it, so a path_corner next to the entity is required.<br />
<br />
For more information, see the editor usage tab for each of these entities.<br />
<br />
== Not yet supported ==<br />
* void path_conversation_listen();<br />
* void path_conversation();<br />
* void path_headanim();<br />
* void path_talk();<br />
* void path_talk_triggered();<br />
* void path_talk_primary();<br />
* void path_talk_secondary();<br />
* void path_waitforheadanim();<br />
* void path_jump();<br />
<br />
* '''path_default''' (not sure if this was even meant to be used)<br />
<br />
* '''path_sentry_*''' These only apply to D3 sentry robots, so there's no reason these should be on DarkMod AI. (Maybe we can use some them though if they're useful for certain AI behaviors, like telling characters when to lead the player and when to leave the player behind)<br />
<br />
[[Category:AI]]<br />
[[Category:Editing]]</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Cvars_in_The_Dark_Mod&diff=6394Cvars in The Dark Mod2008-05-07T15:44:18Z<p>Angua: /* AI */</p>
<hr />
<div>A complete list of Doom 3 Cvars can be found here: http://www.iddevnet.com/doom3/cvars.php<br />
<br />
This should be a list of Cvars that are currently available in the Dark Mod:<br />
<br />
== Inventory ==<br />
* '''tdm_inv_grouping''' Determines whether or not the user-interface uses inventory grouping. It can be changed on the fly without losing the currently selected item.<br />
:* '''0''' means to use a T1/T2 style interface. '''Previous item''' and '''Next item''' are used to scroll through the entire inventory. An empty slot exists between the last and first items of the inventory. '''Previous group''' and '''Next group''' are not functional.<br />
:* '''1''' means to use inventory groups. '''Previous item''' and '''Next item''' are used to scroll through the items in the current group. An empty slot exists between the last and first items of a group. '''Previous group''' and '''Next group''' are used to scroll through the groups of the current inventory in alphabetical order.<br />
:* '''2''' is default, meaning to use a T1/T2 style interface but sort the inventory by group. Items within a given group retain their position relative to eachother, but all items in the first group exist before all items in the second group, and so on. '''Previous item''' and '''Next item''' are used to scroll through the entire inventory. An empty slot exists between the last and first items of the inventory. '''Previous group''' and '''Next group''' are used to scroll through the groups of the current inventory in alphabetical order.<br />
<br />
== HUD ==<br />
* '''tdm_hud_opacity''' : Controls the opacity of the HUD elements. The range is anywhere from '''0''' to '''1''', where '''0''' makes it totally invisible and '''1''' makes it fully opaque. Defaults to 1.<br />
<br />
== Frobbing ==<br />
* '''tdm_frob_ammo_selects_weapon''' (default is "1"): Set this to 1 to have the weapons automatically selected when the respective arrows are frobbed.<br />
<br />
== AI ==<br />
Useful while mapping/testing/designing<br />
* '''tdm_ai_sight''' set to 0 to make AI blind (default 0.7 at time of this writing)<br />
* '''tdm_ai_sndvol''' set to a low negative value, e.g., -300, to make AI deaf (default 0)<br />
* '''tdm_ai_tact''' set to 0 to remove AI sense of touch (default 20)<br />
* '''tdm_ai_showtasks''' shows the current State and Tasks of the AI (see '''[[AI State]]''' and '''[[AI Task]]''').<br />
* '''tdm_ai_showalert''' shows the current alert index and alert level of the AI.<br />
* '''tdm_ai_showdoor''' Debug output during door handling. The goal standing positions for opening and closing the door will be diplayed. At the side of the door where it swings towards, a test with different clipmodel positions is performed to detect whether the AI can stand at this position. A green box indicates that the AI can stand there, while a red box shows that something is in the way. Additionally, the current door handling state of the AI (e.g. MovingToFrontPos, OpeningDoor...) is shown. <br />
* '''tdm_ai_showanimstate''' Shows the current anim states of the anim channels torso, legs and head, as well as their wait states.<br />
<br />
* [[AI Attachment Ingame Editing]]<br />
<br />
== Attachment related ==<br />
The following attachment commands must be run while looking at the AI you want to modify, with nothing obstructing your view. I could have made people type in the full name of the AI, but I'd figure we'd see how it works when looking at them. Also, these are meant to be run after you have initially placed the attachments in the def file / spawnArgs of the AI. This step is still done the same as before.<br />
<br />
* '''tdm_attach_print:''' Print the attachment info for the given attachment on the AI you are looking at.<br />
* Usage: tdm_attach_print <attachment index><br />
<br />
* '''tdm_attach_offset''': Set the vector offset (x y z) for an attachment on an AI you are looking at.<br />
* Usage: tdm_attach_offset <attachment index> <x> <y> <z><br />
<br />
* '''tdm_attach_rot''': Set the rotation (pitch yaw roll) for an attachment on an AI you are looking at.<br />
* Usage: tdm_attach_rot <atachment index> <pitch> <yaw> <roll> (NOTE: Rotation is applied before translation, angles are relative to the joint orientation)<br />
<br />
* '''tdm_attach_joint''': Set the attachment joint name for an attachment on an AI you are looking at.<br />
Usage: tdm_attach_joint <attachment index> <string name of joint><br />
<br />
{{scripting}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=Cvars_in_The_Dark_Mod&diff=6393Cvars in The Dark Mod2008-05-07T15:02:07Z<p>Angua: /* AI */</p>
<hr />
<div>A complete list of Doom 3 Cvars can be found here: http://www.iddevnet.com/doom3/cvars.php<br />
<br />
This should be a list of Cvars that are currently available in the Dark Mod:<br />
<br />
== Inventory ==<br />
* '''tdm_inv_grouping''' Determines whether or not the user-interface uses inventory grouping. It can be changed on the fly without losing the currently selected item.<br />
:* '''0''' means to use a T1/T2 style interface. '''Previous item''' and '''Next item''' are used to scroll through the entire inventory. An empty slot exists between the last and first items of the inventory. '''Previous group''' and '''Next group''' are not functional.<br />
:* '''1''' means to use inventory groups. '''Previous item''' and '''Next item''' are used to scroll through the items in the current group. An empty slot exists between the last and first items of a group. '''Previous group''' and '''Next group''' are used to scroll through the groups of the current inventory in alphabetical order.<br />
:* '''2''' is default, meaning to use a T1/T2 style interface but sort the inventory by group. Items within a given group retain their position relative to eachother, but all items in the first group exist before all items in the second group, and so on. '''Previous item''' and '''Next item''' are used to scroll through the entire inventory. An empty slot exists between the last and first items of the inventory. '''Previous group''' and '''Next group''' are used to scroll through the groups of the current inventory in alphabetical order.<br />
<br />
== HUD ==<br />
* '''tdm_hud_opacity''' : Controls the opacity of the HUD elements. The range is anywhere from '''0''' to '''1''', where '''0''' makes it totally invisible and '''1''' makes it fully opaque. Defaults to 1.<br />
<br />
== Frobbing ==<br />
* '''tdm_frob_ammo_selects_weapon''' (default is "1"): Set this to 1 to have the weapons automatically selected when the respective arrows are frobbed.<br />
<br />
== AI ==<br />
Useful while mapping/testing/designing<br />
* '''tdm_ai_sight''' set to 0 to make AI blind (default 0.7 at time of this writing)<br />
* '''tdm_ai_sndvol''' set to a low negative value, e.g., -300, to make AI deaf (default 0)<br />
* '''tdm_ai_tact''' set to 0 to remove AI sense of touch (default 20)<br />
* '''tdm_ai_showtasks''' shows the current State and Tasks of the AI (see '''[[AI State]]''' and '''[[AI Task]]''').<br />
* '''tdm_ai_showalert''' shows the current alert index and alert level of the AI.<br />
* '''tdm_ai_showdoor''' Debug output during door handling. The goal standing positions for opening and closing the door will be diplayed. At the side of the door where it swings towards, a test with different clipmodel positions is performed to detect whether the AI can stand at this position. A green box indicates that the AI can stand there, while a red box shows that something is in the way. Additionally, the current door handling state of the AI (e.g. MovingToFrontPos, OpeningDoor...) is shown. <br />
<br />
* [[AI Attachment Ingame Editing]]<br />
<br />
== Attachment related ==<br />
The following attachment commands must be run while looking at the AI you want to modify, with nothing obstructing your view. I could have made people type in the full name of the AI, but I'd figure we'd see how it works when looking at them. Also, these are meant to be run after you have initially placed the attachments in the def file / spawnArgs of the AI. This step is still done the same as before.<br />
<br />
* '''tdm_attach_print:''' Print the attachment info for the given attachment on the AI you are looking at.<br />
* Usage: tdm_attach_print <attachment index><br />
<br />
* '''tdm_attach_offset''': Set the vector offset (x y z) for an attachment on an AI you are looking at.<br />
* Usage: tdm_attach_offset <attachment index> <x> <y> <z><br />
<br />
* '''tdm_attach_rot''': Set the rotation (pitch yaw roll) for an attachment on an AI you are looking at.<br />
* Usage: tdm_attach_rot <atachment index> <pitch> <yaw> <roll> (NOTE: Rotation is applied before translation, angles are relative to the joint orientation)<br />
<br />
* '''tdm_attach_joint''': Set the attachment joint name for an attachment on an AI you are looking at.<br />
Usage: tdm_attach_joint <attachment index> <string name of joint><br />
<br />
{{scripting}}</div>Anguahttps://wiki.thedarkmod.com/index.php?title=AI_State&diff=6392AI State2008-05-07T14:53:20Z<p>Angua: /* Backbone States */</p>
<hr />
<div>An AI's Mind is in a certain State all the time. It's the State class which does the actual thinking each frame, it pushes the Tasks to the Subsystems, it interprets the incoming stimuli, it decides which States the Mind will be switch to.<br />
<br />
'''Note''': States are the '''only''' instances which are allowed to actually switch the Mind's State (Tasks are not allowed to do it, nor is the Mind or the AI class itself allowed to). Also, States are the only instances which are allowed to delegate Tasks into the Subsystems.<br />
<br />
States are allowed to Think() once per frame. This method is invoked by the Mind and gives them an opportunity to monitor their Tasks and to switch to other States.<br />
<br />
== Backbone States ==<br />
<br />
There are a few so-called Backbone States, corresponding to the AI's alert indices:<br />
* Alert Index '''0''' => '''IdleState''' (which is replaced by '''AlertIdleState''' when the AI has seen evidence of intruders)<br />
* Alert Index '''1''' => '''ObservantState'''<br />
* Alert Index '''2''' => '''SuspiciousState'''<br />
* Alert Index '''3''' => '''SearchingState'''<br />
* Alert Index '''4''' => '''AgitatedSearchingState'''<br />
* Alert Index '''5''' => '''CombatState''' (only allowed if Enemy is known)<br />
<br />
The Backbone States form some kind of "ladder" and follow this pattern:<br />
<br />
* When the AI's alert level '''exceeds''' a given threshold (e.g. from thresh_4 to thresh_5), the Backbone State switches to the next higher State (e.g. from '''AgitatedSearchingState''' to '''CombatState'''). This happens via a '''PushState''' command, so that the AgitatedSearchingState still stays within the Mind's StateQueue.<br />
* When the AI's alert level '''falls below''' the threshold for the current State, it is terminated via an '''EndState''' call. <br />
<br />
These two rules ensure that the Mind is always in the correct State according to the AI's alert index. Consequently, you don't need to actually switch to a higher Backbone State (in fact you're not allowed to), this is accomplished by calling '''SetAlertLevel''' instead. The States monitor the alert level changes on their own and automatically switch to the correct State. <br />
<br />
Example: Let's assume the AI is in SearchingState and encounters the player (visually). The alert index is increased immediately above ''thresh_5'' which causes the SearchingState (in its role as Backbone State) to Push the next higher State (in this case this is AgitatedSearchingState). The AgitatedSearchingState peforms another check and as the alertlevel is higher than thresh_5 it passes the torch and pushes the CombatState into the StateQueue. Let's further assume that the player manages to escape and the AI's alert level is slowly decreasing again. As soon as it falls below ''thresh_5'', the CombatState recognises itself not being appropriate anymore and calls EndState(). This lets the Mind fall back into the AgitatedSearchingState (which is still in the Mind's StateQueue). A further decrease of the Alert Level causes the AgitatedSearchingState to end itself and to fall back to SearchingState. This goes on until the bottom of the StateQueue is reached, which is always occupied by the IdleState.<br />
<br />
The important part is that the Backbone States always use '''PushState''' to go ''upwards'' and '''EndState''' to go ''downwards''.<br />
<br />
It's of course not a problem, if the CombatState decides to switch to some other State like FleeState or LostTrackOfEnemyState, as long as the BackBone stays intact. It's ok for the CombatState to use either SwitchState, PushState to jump to (say) FleeState. The important thing is that the FleeState must not directly push another Backbone State (like IdleState), as this would disrupt the StateQueue. If the FleeState wants to go back into IdleState, it's enough to set the AI alert level and call EndState. The BackBone States will take care of switching by subsequently calling EndState until the corresponding State is reached.<br />
{{Things-To-Remember|<br />
* Only States are allowed to switch States<br />
* Only Backbone States are allowed to switch to one of the six Backbone States (via PushState/EndState).<br />
* The Backbone States always take care that the right State is selected when the Alert Index is changing.<br />
* State switches between Backbone States must happen via AI::SetAlertLevel.<br />
* States are responsible for handling the incoming stimuli and pushing the right Tasks into their Subsystems.<br />
}}<br />
<br />
== Implementation Notes ==<br />
A State must...<br />
* ...have a unique name string identifier (depicted in the header, e.g. STATE_COMBAT).<br />
* ...implement the abstract State interface<br />
* ...provide a static CreateInstance() method.<br />
* ...register itself with the StateLibrary using a StateRegistrar helper class.<br />
* ...define a default constructor without arguments<br />
* ...be save-able and restore-able via the Save/Restore methods it has to implement (no reference/raw pointer members, etc., see Saving and Loading)<br />
<br />
Optional: A State can...<br />
* ...implement the method OnSubsystemTaskFinished to get notified about finished Subsystem Tasks.<br />
* ...override one of the various OnVisualStimX() methods to implement behaviour different to the default.<br />
* ...override the OnAICommMessage() to handle the incoming messages differently than the base class.<br />
<br />
=== Backbone States ===<br />
The Backbone States override the default implementation '''bool State::CheckAlertLevel()''' and implement a check using a required alert index and the name of the higher State. If the alert index is not matching, it switches to the state below or above. For switching to the State "below" (e.g. from AgitatedSearching to Searching) it just takes a call to EndState() whereas for switching to the higher state, the actual name is needed (AgitatedSearchingState would pass the STATE_COMBAT string constant to the method).<br />
<br />
This method is checked each time the Backbone State is about to think or initialise, so setting the alert level/index almost instantly triggers a switch to the right State.<br />
<br />
The call to CheckAlertLevel() can also be used by other, non-backbone States, where appropriate.<br />
<br />
[[Category:AI]]<br />
[[Category:Scripting]]<br />
[[Category:Coding]]</div>Angua