1-- Set the namespace according to the map name. 2local ns = {}; 3setmetatable(ns, {__index = _G}); 4layna_village_well_underground_script = ns; 5setfenv(1, ns); 6 7-- The map name, subname and location image 8map_name = "Mountain Village of Layna" 9map_image_filename = "data/story/common/locations/mountain_village.png" 10map_subname = "Well Undergrounds" 11 12-- The music file used as default background music on this map. 13-- Other musics will have to handled through scripting. 14music_filename = "data/music/shrine-OGA-yd.ogg" 15 16-- c++ objects instances 17local Map = nil 18local Script = nil 19local EventManager = nil 20 21-- Characters handler 22local bronann = nil 23local olivia = nil 24local hero = nil 25 26-- the main map loading code 27function Load(m) 28 29 Map = m; 30 Script = Map:GetScriptSupervisor() 31 EventManager = Map:GetEventSupervisor() 32 33 _CreateCharacters() 34 _CreateObjects() 35 36 -- Put last to get a proper night effect 37 Script:AddScript("data/story/common/lost_in_darkness.lua"); 38 39 -- Set the camera focus on bronann 40 Map:SetCamera(bronann) 41 42 _CreateEvents() 43 _CreateZones() 44 _CreateEnemies() 45end 46 47-- the map update function handles checks done on each game tick. 48function Update() 49 -- Check whether the character is in one of the zones 50 _CheckZones() 51 52 _UpdateLampLocation() 53 54 _CheckMonstersState() 55end 56 57-- Character creation 58function _CreateCharacters() 59 60 bronann = CreateSprite(Map, "Bronann", 18, 3, vt_map.MapMode.GROUND_OBJECT) 61 bronann:SetDirection(vt_map.MapMode.SOUTH) 62 bronann:SetMovementSpeed(vt_map.MapMode.NORMAL_SPEED) 63 hero = bronann 64 65 olivia = CreateNPCSprite(Map, "Girl1", vt_system.Translate("Olivia"), 18, 3, vt_map.MapMode.GROUND_OBJECT) 66 olivia:SetDirection(vt_map.MapMode.SOUTH) 67 olivia:SetMovementSpeed(vt_map.MapMode.NORMAL_SPEED) 68end 69 70-- oil lamp 71local oil_lamp = nil 72local lamp_halo = nil 73local lamp_flare = nil 74 75-- The heal particle effect map object 76local heal_effect = nil 77 78function _CreateObjects() 79 -- Info sign 80 local object = CreateObject(Map, "Wood sign info", 5, 12, vt_map.MapMode.GROUND_OBJECT) 81 object:SetEventWhenTalking("Info about equipment") 82 local dialogue = vt_map.SpriteDialogue.Create(); 83 local text = vt_system.Translate("Did you know?\nYou can equip weapons and armors from the menu.\nSimply open it and go to 'Inventory', and 'Equip'."); 84 dialogue:AddLine(text, nil); 85 local event = vt_map.DialogueEvent.Create("Info about equipment", dialogue) 86 87 oil_lamp = CreateObject(Map, "Oil Lamp", 15, 14, vt_map.MapMode.GROUND_OBJECT) 88 oil_lamp:SetCollisionMask(vt_map.MapMode.NO_COLLISION) 89 local lamp_x_pos = oil_lamp:GetXPosition() 90 local lamp_y_pos = oil_lamp:GetYPosition() 91 92 lamp_halo = vt_map.Halo.Create("data/visuals/lights/torch_light_mask2.lua", lamp_x_pos, lamp_y_pos, 93 vt_video.Color(0.9, 0.9, 0.4, 0.5)) 94 lamp_flare = vt_map.Halo.Create("data/visuals/lights/sun_flare_light_main.lua", lamp_x_pos, lamp_y_pos, 95 vt_video.Color(0.99, 1.0, 0.27, 0.2)) 96 _SetLampPosition(lamp_x_pos, lamp_y_pos) 97 98 -- hide it when the intro event is not done yet. 99 if (GlobalManager:GetGameEvents():DoesEventExist("story", "well_intro_event_done") == false) then 100 oil_lamp:SetVisible(false) 101 lamp_halo:SetVisible(false) 102 lamp_flare:SetVisible(false) 103 end 104 105 -- Add the heal icon 106 local npc = CreateObject(Map, "Layna Statue", 11, 10, vt_map.MapMode.GROUND_OBJECT); 107 npc:SetCollisionMask(vt_map.MapMode.NO_COLLISION); 108 npc:SetInteractionIcon("data/gui/map/heal_anim.lua") 109 npc = CreateSprite(Map, "Butterfly", 11, 10, vt_map.MapMode.GROUND_OBJECT); 110 npc:SetCollisionMask(vt_map.MapMode.NO_COLLISION); 111 npc:SetVisible(false); 112 npc:SetName(""); -- Unset the speaker name 113 dialogue = vt_map.SpriteDialogue.Create(); 114 text = vt_system.Translate("Your party feels better."); 115 dialogue:AddLineEvent(text, npc, "Well entrance heal", ""); 116 npc:AddDialogueReference(dialogue); 117 118 vt_map.ScriptedEvent.Create("Well entrance heal", "heal_party", "heal_done"); 119 120 -- Load the spring heal effect. 121 heal_effect = vt_map.ParticleObject.Create("data/visuals/particle_effects/heal_particle.lua", 0, 0, vt_map.MapMode.GROUND_OBJECT); 122 heal_effect:Stop(); -- Don't run it until the character heals itself 123 124 CreateObject(Map, "Rock1", 59, 11.2, vt_map.MapMode.GROUND_OBJECT) 125 CreateObject(Map, "Rock1", 3, 43, vt_map.MapMode.GROUND_OBJECT) 126 CreateObject(Map, "Rock1", 5.5, 43.2, vt_map.MapMode.GROUND_OBJECT) 127 CreateObject(Map, "Rock1", 60, 25, vt_map.MapMode.GROUND_OBJECT) 128 129 local chest = CreateTreasure(Map, "well_underground_chest", "Wood_Chest2", 57, 11.5, vt_map.MapMode.GROUND_OBJECT) 130 chest:AddItem(1, 3) 131end 132 133local lamp_character = nil 134 135function _UpdateLampLocation() 136 -- Stick the lamp to a given character reference 137 -- if the reference is nil, just let the lamp where it is. 138 if (lamp_character == nil) then 139 return 140 end 141 142 -- Sets the lamp location depending on the character's location and orientation 143 local character_direction = lamp_character:GetDirection() 144 local x_pos = lamp_character:GetXPosition() 145 local y_pos = lamp_character:GetYPosition() 146 local x_offset = 0.0 147 local y_offset = 0.0 148 if (character_direction == vt_map.MapMode.WEST 149 or character_direction == vt_map.MapMode.NW_WEST 150 or character_direction == vt_map.MapMode.SW_WEST) then 151 x_offset = -0.5 152 y_offset = -0.5 153 elseif (character_direction == vt_map.MapMode.EAST 154 or character_direction == vt_map.MapMode.NE_EAST 155 or character_direction == vt_map.MapMode.SE_EAST) then 156 x_offset = 0.5 157 y_offset = -0.5 158 elseif (character_direction == vt_map.MapMode.NORTH 159 or character_direction == vt_map.MapMode.NW_NORTH 160 or character_direction == vt_map.MapMode.NE_NORTH) then 161 x_offset = -0.5 162 y_offset = -0.5 163 elseif (character_direction == vt_map.MapMode.SOUTH 164 or character_direction == vt_map.MapMode.SW_SOUTH 165 or character_direction == vt_map.MapMode.SE_SOUTH) then 166 x_offset = 0.5 167 y_offset = -0.5 168 end 169 170 _SetLampPosition(x_pos + x_offset, y_pos + y_offset) 171end 172 173-- Handles the fixed offsets betwwen the oil_lamp object, and the related ones 174function _SetLampPosition(x, y) 175 oil_lamp:SetPosition(x, y) 176 lamp_halo:SetPosition(x, y + 4.0) 177 lamp_flare:SetPosition(x, y + 2.0) 178end 179 180-- Special roam zones used to test whether Bronann did the fights 181local roam_zone1 = nil 182local roam_zone2 = nil 183local roam_zone3 = nil 184local rats_beaten = false 185 186function _CreateEnemies() 187 local enemy = nil 188 189 -- Hint: left, right, top, bottom 190 roam_zone1 = vt_map.EnemyZone.Create(48, 61, 2, 20) 191 enemy = CreateEnemySprite(Map, "ratto") 192 _SetBattleEnvironment(enemy) 193 enemy:NewEnemyParty() 194 enemy:AddEnemy(22) 195 roam_zone1:AddEnemy(enemy, 2) 196 roam_zone1:SetSpawnsLeft(1); -- This monster shall spawn only one time. 197 198 -- Hint: left, right, top, bottom 199 roam_zone2 = vt_map.EnemyZone.Create(2, 10, 42, 63) 200 enemy = CreateEnemySprite(Map, "ratto") 201 _SetBattleEnvironment(enemy) 202 enemy:NewEnemyParty() 203 enemy:AddEnemy(22) 204 roam_zone2:AddEnemy(enemy, 2) 205 roam_zone2:SetSpawnsLeft(1); -- This monster shall spawn only one time. 206 207 -- Hint: left, right, top, bottom 208 roam_zone3 = vt_map.EnemyZone.Create(58, 60, 58, 60) 209 enemy = CreateEnemySprite(Map, "ratto") 210 _SetBattleEnvironment(enemy) 211 enemy:NewEnemyParty() 212 enemy:AddEnemy(22) 213 enemy:AddEnemy(22) 214 enemy:SetBoss(true) 215 roam_zone3:AddEnemy(enemy, 1) 216 roam_zone3:SetSpawnsLeft(1); -- This monster shall spawn only one time. 217end 218 219function _CheckMonstersState() 220 if (rats_beaten == false and roam_zone1:GetSpawnsLeft() == 0 and roam_zone2:GetSpawnsLeft() == 0 and roam_zone3:GetSpawnsLeft() == 0) then 221 if (GlobalManager:GetGameEvents():DoesEventExist("story", "well_rats_beaten") == false) then 222 rats_beaten = true 223 224 -- Update Olivia dialogue to let Bronann go out 225 olivia:ClearDialogueReferences() 226 local dialogue = vt_map.SpriteDialogue.Create() 227 local text = vt_system.Translate("Congratulations, Bronann. Here is your reward.") 228 dialogue:AddLineEmote(text, olivia, "exclamation") 229 dialogue:SetEventAtDialogueEnd("Bronann receives reward") 230 olivia:AddDialogueReference(dialogue) 231 232 local event = vt_map.TreasureEvent.Create("Bronann receives reward"); 233 event:AddItem(40002, 1) -- Long leather gloves 234 event:AddEventLinkAtEnd("Olivia leaves"); 235 236 event = vt_map.PathMoveSpriteEvent.Create("Olivia leaves", olivia, 18, 1, false) 237 event:AddEventLinkAtEnd("Set Olivia invisible") 238 239 event = vt_map.ScriptedEvent.Create("Set Olivia invisible", "make_olivia_invisible", "") 240 241 -- Set intro event as done 242 GlobalManager:GetGameEvents():SetEventValue("story", "well_rats_beaten", 1); 243 end 244 end 245end 246 247-- Sets common battle environment settings for enemy sprites 248function _SetBattleEnvironment(enemy) 249 enemy:SetBattleMusicTheme("data/music/heroism-OGA-Edward-J-Blakeley.ogg") 250 enemy:SetBattleBackground("data/battles/battle_scenes/desert_cave/desert_cave.png") 251 enemy:AddBattleScript("data/battles/battle_scenes/desert_cave_battle_anim.lua") 252 enemy:AddBattleScript("data/story/common/lost_in_darkness.lua") 253 -- Add tutorial battle dialog with Olivia 254 enemy:AddBattleScript("data/story/common/tutorial_battle_dialogs.lua"); 255 -- TODO: Add oil lamp as scenery in battles 256end 257 258-- Creates all events and sets up the entire event sequence chain 259function _CreateEvents() 260 local event = nil 261 local dialogue = nil 262 local text = nil 263 264 -- Triggered events 265 vt_map.MapTransitionEvent.Create("exit floor", "data/story/layna_village/layna_village_center_map.lua", 266 "data/story/layna_village/layna_village_center_script.lua", 267 "from_well_undergrounds") 268 269 -- Generic events 270 vt_map.LookAtSpriteEvent.Create("Olivia looks at Bronann", olivia, bronann) 271 vt_map.LookAtSpriteEvent.Create("Bronann looks at Olivia", bronann, olivia) 272 vt_map.ChangeDirectionSpriteEvent.Create("Bronann looks south", bronann, vt_map.MapMode.SOUTH) 273 vt_map.ChangeDirectionSpriteEvent.Create("Bronann looks east", bronann, vt_map.MapMode.EAST) 274 275 if (GlobalManager:GetGameEvents():DoesEventExist("story", "well_intro_event_done") == false) then 276 event = vt_map.ScriptedEvent.Create("Well undergrounds scene start", "well_intro_scene_start", "") 277 event:AddEventLinkAtEnd("Olivia takes a few steps") 278 279 event = vt_map.PathMoveSpriteEvent.Create("Olivia takes a few steps", olivia, 18, 13, false) 280 event:AddEventLinkAtEnd("Olivia shows the oil lamp", 1000) 281 282 event = vt_map.ScriptedEvent.Create("Olivia shows the oil lamp", "oil_lamp_move_start", "oil_lamp_move_update") 283 event:AddEventLinkAtEnd("Olivia lights the oil lamp", 1000) 284 285 event = vt_map.ScriptedEvent.Create("Olivia lights the oil lamp", "oil_lamp_light", "") 286 event:AddEventLinkAtEnd("Olivia looks at Bronann", 1000) 287 event:AddEventLinkAtEnd("Olivia goes near the fountain", 2000) 288 289 event = vt_map.PathMoveSpriteEvent.Create("Olivia goes near the fountain", olivia, 10, 14, false) 290 event:AddEventLinkAtEnd("Olivia looks at Bronann") 291 event:AddEventLinkAtEnd("Olivia tells Bronann to come in the undergrounds", 1000) 292 293 dialogue = vt_map.SpriteDialogue.Create() 294 text = vt_system.Translate("You can come, Bronann.") 295 dialogue:AddLine(text, olivia) 296 event = vt_map.DialogueEvent.Create("Olivia tells Bronann to come in the undergrounds", dialogue) 297 event:AddEventLinkAtEnd("Bronann goes near Olivia") 298 299 event = vt_map.PathMoveSpriteEvent.Create("Bronann goes near Olivia", bronann, 12, 14, false) 300 event:AddEventLinkAtEnd("Bronann looks at Olivia") 301 event:AddEventLinkAtEnd("Olivia tells Bronann about the undergrounds", 1000) 302 303 dialogue = vt_map.SpriteDialogue.Create() 304 text = vt_system.Translate("This is one of the many secrets of this village.") 305 dialogue:AddLine(text, olivia) 306 text = vt_system.Translate("This village was once a sanctuary and many people lived around here. Surprising, eh?") 307 dialogue:AddLineEvent(text, olivia, "", "Bronann looks south") 308 text = vt_system.Translate("Your father told me you were now ready.") 309 dialogue:AddLineEvent(text, olivia, "", "Bronann looks east") 310 text = vt_system.Translate("Huh? Ready for what?") 311 dialogue:AddLineEmote(text, bronann, "exclamation") 312 text = vt_system.Translate("For your first true trial.") 313 dialogue:AddLineEvent(text, olivia, "Olivia looks at Bronann", "") 314 text = vt_system.Translate("I know I will sound harsh Bronann, but we've been having issues with rats in the well recently.") 315 dialogue:AddLineEvent(text, olivia, "Bronann looks at Olivia", "") 316 text = vt_system.Translate("You're now going to go deep down this cave and chase them all before they start polluting our water.") 317 dialogue:AddLine(text, olivia) 318 text = vt_system.Translate("All by yourself.") 319 dialogue:AddLine(text, olivia) 320 text = vt_system.Translate("I'll stay around but I won't participate. This... will prepare you for the days to come.") 321 dialogue:AddLineEmote(text, olivia, "thinking dots") 322 text = vt_system.Translate("Take this lamp, your father gave it to me earlier. You can keep it.") 323 dialogue:AddLineEvent(text, olivia, "Move lamp near Bronann", "") 324 325 event = vt_map.ScriptedEvent.Create("Move lamp near Bronann", "move_lamp_to_bronann_start", "move_lamp_to_bronann_update") 326 327 text = vt_system.Translate("You can use the fountain here to restore your health, but you are to complete this before going out again. Not too afraid?") 328 dialogue:AddLine(text, olivia) 329 text = vt_system.Translate("I'm completely panicking, Olivia. Why now?") 330 dialogue:AddLineEmote(text, bronann, "exclamation") 331 text = vt_system.Translate("It will be fine.") 332 dialogue:AddLine(text, olivia) 333 event = vt_map.DialogueEvent.Create("Olivia tells Bronann about the undergrounds", dialogue) 334 event:AddEventLinkAtEnd("Olivia goes to the entrance and watch") 335 336 event = vt_map.PathMoveSpriteEvent.Create("Olivia goes to the entrance and watch", olivia, 18, 6, false) 337 event:AddEventLinkAtEnd("Olivia looks at Bronann") 338 event:AddEventLinkAtEnd("Olivia tells Bronann to go") 339 340 dialogue = vt_map.SpriteDialogue.Create() 341 text = vt_system.Translate("You can make it.") 342 dialogue:AddLine(text, olivia) 343 event = vt_map.DialogueEvent.Create("Olivia tells Bronann to go", dialogue) 344 event:AddEventLinkAtEnd("Well undergrounds scene end") 345 346 event = vt_map.ScriptedEvent.Create("Well undergrounds scene end", "well_intro_scene_end", "") 347 348 -- Make the whole scene start at map fade in 349 EventManager:StartEvent("Well undergrounds scene start"); 350 elseif (GlobalManager:GetGameEvents():DoesEventExist("story", "well_rats_beaten") == false) then 351 -- Should not happen 352 else 353 -- Stick the lamp to Bronann and make it visible 354 lamp_character = bronann 355 oil_lamp:SetVisible(true) 356 lamp_halo:SetVisible(true) 357 lamp_flare:SetVisible(true) 358 359 -- Disable Olivia when the event is done. 360 olivia:SetVisible(false) 361 olivia:SetPosition(0, 0) 362 end 363end 364 365-- zones 366local room_exit_zone = nil 367 368-- Create the different map zones triggering events 369function _CreateZones() 370 -- N.B.: left, right, top, bottom 371 room_exit_zone = vt_map.CameraZone.Create(16, 18, 0, 1) 372end 373 374-- Check whether the active camera has entered a zone. To be called within Update() 375function _CheckZones() 376 if (room_exit_zone:IsCameraEntering() == true) then 377 bronann:SetMoving(false); 378 EventManager:StartEvent("exit floor") 379 end 380end 381 382 383-- Map Custom functions 384-- Used through scripted events 385 386local oil_lamp_move_x_pos = 0 387local oil_lamp_move_y_pos = 0 388local oil_lamp_move_y_pos_end = 0 389local oil_lamp_move_y_pos_end = 0 390 391-- Effect time used when applying the heal light effect 392local heal_effect_time = 0; 393local heal_color = vt_video.Color(0.0, 0.0, 1.0, 1.0); 394 395map_functions = { 396 397 well_intro_scene_start = function() 398 Map:PushState(vt_map.MapMode.STATE_SCENE) 399 bronann:SetMoving(false) 400 end, 401 402 -- make oil lamp appear in front of Olivia 403 oil_lamp_move_start = function() 404 oil_lamp_move_y_pos = olivia:GetYPosition() - 1.0 405 _SetLampPosition(olivia:GetXPosition() + 0.5, oil_lamp_move_y_pos) 406 oil_lamp:SetVisible(true) 407 oil_lamp_move_y_pos_end = oil_lamp_move_y_pos + 0.5 408 end, 409 410 oil_lamp_move_update = function() 411 oil_lamp_move_y_pos = oil_lamp_move_y_pos + SystemManager:GetUpdateTime() / 200 412 _SetLampPosition(olivia:GetXPosition() + 0.5, oil_lamp_move_y_pos) 413 if (oil_lamp_move_y_pos < oil_lamp_move_y_pos_end) then 414 return false 415 end 416 -- Stick the lamp to Olivia 417 lamp_character = olivia 418 return true 419 end, 420 421 oil_lamp_light = function() 422 lamp_flare:SetVisible(true) 423 lamp_halo:SetVisible(true) 424 end, 425 426 move_lamp_to_bronann_start = function() 427 -- unstick lamp from Olivia 428 lamp_character = nil 429 -- Set starting coords 430 oil_lamp_move_x_pos = oil_lamp:GetXPosition() 431 oil_lamp_move_y_pos = oil_lamp:GetYPosition() 432 oil_lamp_move_x_pos_end = oil_lamp_move_x_pos + 0.5 433 oil_lamp_move_y_pos_end = oil_lamp_move_y_pos - 0.5 434 end, 435 436 move_lamp_to_bronann_update = function() 437 local move_update = SystemManager:GetUpdateTime() / 200 438 _SetLampPosition(oil_lamp_move_x_pos, oil_lamp_move_y_pos) 439 if (oil_lamp_move_y_pos > oil_lamp_move_y_pos_end) then 440 oil_lamp_move_y_pos = oil_lamp_move_y_pos - move_update 441 return false 442 end 443 if (oil_lamp_move_x_pos < oil_lamp_move_x_pos_end) then 444 oil_lamp_move_x_pos = oil_lamp_move_x_pos + move_update 445 return false 446 end 447 -- Stick the lamp to Bronann 448 lamp_character = bronann 449 return true 450 end, 451 452 well_intro_scene_end = function() 453 -- Set new Olivia dialogue 454 olivia:ClearDialogueReferences() 455 local dialogue = vt_map.SpriteDialogue.Create() 456 local text = vt_system.Translate("Bronann. Sorry, you have to complete this first.") 457 dialogue:AddLine(text, olivia) 458 text = vt_system.Translate("You can use the fountain here to restore your health.") 459 dialogue:AddLine(text, olivia) 460 olivia:AddDialogueReference(dialogue) 461 -- Set intro event as done 462 GlobalManager:GetGameEvents():SetEventValue("story", "well_intro_event_done", 1) 463 Map:PopState() 464 end, 465 466 heal_party = function() 467 hero:SetMoving(false); 468 -- Should be sufficient to heal anybody 469 local character_handler = GlobalManager:GetCharacterHandler() 470 character_handler:GetActiveParty():AddHitPoints(10000) 471 character_handler:GetActiveParty():AddSkillPoints(10000) 472 Map:SetStamina(10000) 473 Map:RemoveNegativeActiveStatusEffects() 474 AudioManager:PlaySound("data/sounds/heal_spell.wav"); 475 heal_effect:SetPosition(hero:GetXPosition(), hero:GetYPosition()); 476 heal_effect:Start(); 477 heal_effect_time = 0; 478 end, 479 480 heal_done = function() 481 heal_effect_time = heal_effect_time + SystemManager:GetUpdateTime(); 482 483 if (heal_effect_time < 300.0) then 484 heal_color:SetAlpha(heal_effect_time / 300.0 / 3.0); 485 Map:GetEffectSupervisor():EnableLightingOverlay(heal_color); 486 return false; 487 end 488 489 if (heal_effect_time < 1000.0) then 490 heal_color:SetAlpha(((1000.0 - heal_effect_time) / 700.0) / 3.0); 491 Map:GetEffectSupervisor():EnableLightingOverlay(heal_color); 492 return false; 493 end 494 return true; 495 end, 496 497 make_olivia_invisible = function() 498 olivia:SetVisible(false) 499 olivia:SetPosition(0, 0) 500 end, 501} 502