2461 lines
62 KiB
Lua
2461 lines
62 KiB
Lua
local USE_EVENT_USE = 0x01
|
|
local USE_EVENT_MOVE = 0x40
|
|
local USE_EVENT_READY = 0x0100
|
|
|
|
function search_container(obj)
|
|
local child
|
|
for child in container_objs(obj) do
|
|
Obj.moveToMap(child, obj.x, obj.y, obj.z)
|
|
end
|
|
end
|
|
|
|
function use_door(obj, actor)
|
|
if bit32.btest(obj.quality, 0x80) then
|
|
printl("IT_IS_LOCKED")
|
|
return
|
|
end
|
|
|
|
if map_get_actor(obj.x, obj.y, obj.z) ~= nil then
|
|
printl("BLOCKED")
|
|
return
|
|
end
|
|
|
|
obj.frame_n = bit32.bxor(obj.frame_n, 2)
|
|
|
|
end
|
|
|
|
function use_crate(obj, target_obj, actor)
|
|
if target_obj.frame_n == 2 then
|
|
target_obj.frame_n = 1
|
|
printl("YOU_PRIED_THE_NAILS_OUT_OF_THE_CRATE")
|
|
else
|
|
if target_obj.frame_n == 1 and obj.obj_n == 273 then
|
|
target_obj.frame_n = 2
|
|
printl("YOU_NAIL_THE_CRATE_SHUT")
|
|
else
|
|
printl("IT_HAS_NO_EFFECT")
|
|
end
|
|
end
|
|
end
|
|
|
|
function use_container(obj, actor)
|
|
if obj.frame_n == 2 then
|
|
if obj.obj_n == 86 or obj.obj_n == 284 then
|
|
printl("IT_IS_NAILED_SHUT")
|
|
else
|
|
printl("IT_IS_LOCKED")
|
|
end
|
|
else
|
|
if obj.frame_n == 1 then
|
|
obj.frame_n = 0
|
|
search_container(obj)
|
|
else
|
|
obj.frame_n = 1
|
|
end
|
|
end
|
|
end
|
|
|
|
function use_hammer_on_oxium_geode(obj, target_obj, actor)
|
|
if target_obj.frame_n ~= 0 then
|
|
printl("IT_HAS_NO_EFFECT")
|
|
return
|
|
end
|
|
|
|
play_md_sfx(0x20)
|
|
target_obj.frame_n = 1 --break the geode open
|
|
|
|
if target_obj.on_map then
|
|
local oxium = Obj.new(131) --OBJ_BLOB_OF_OXIUM
|
|
oxium.qty = math.random(1, 50) + math.random(1, 50)
|
|
Obj.moveToMap(oxium, target_obj.x, target_obj.y, target_obj.z)
|
|
else
|
|
--FIXME add to actor's inventory
|
|
local oxium = Actor.inv_get_obj_n(actor, 131) --OBJ_BLOB_OF_OXIUM
|
|
local qty = math.random(1, 50) + math.random(1, 50)
|
|
if oxium ~= nil then
|
|
oxium.qty = oxium.qty + qty
|
|
else
|
|
oxium = Obj.new(131, 0, 0, qty) --OBJ_BLOB_OF_OXIUM
|
|
Actor.inv_add_obj(actor, oxium)
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
function use_prybar_on_hatch(obj, target_obj, actor)
|
|
|
|
if actor.actor_num ~= 1 then
|
|
printfl("IS_NOT_STRONG_ENOUGH", actor.name)
|
|
return
|
|
end
|
|
|
|
local tesla = Actor.get(16)
|
|
if Actor.get_talk_flag(tesla, 4) == false then
|
|
Actor.set_talk_flag(tesla, 2)
|
|
Actor.talk(tesla)
|
|
else
|
|
play_midgame_sequence(1)
|
|
|
|
Actor.set_talk_flag(tesla, 5)
|
|
target_obj.obj_n = 428
|
|
target_obj.frame_n = 0;
|
|
target_obj.x = target_obj.x + 1
|
|
target_obj.y = target_obj.y + 1
|
|
|
|
local blood = Actor.get(18)
|
|
Actor.set_talk_flag(blood, 3)
|
|
Actor.set_talk_flag(blood, 6)
|
|
Actor.talk(blood)
|
|
end
|
|
end
|
|
|
|
function use_sextant(obj, actor)
|
|
if actor.z ~= 0 then
|
|
printl("NOT_WHILE_UNDERGROUND")
|
|
return
|
|
end
|
|
|
|
local lat_str = "N"
|
|
local long_str = "W"
|
|
|
|
local lat = math.modf(((actor.y - 512) * 240) / 1024)
|
|
local long = math.modf(((actor.x - 512) * 360) / 1024)
|
|
|
|
if lat > 0 then
|
|
lat_str = "S"
|
|
else
|
|
if lat == 0 then
|
|
lat_str = " "
|
|
end
|
|
end
|
|
|
|
if long == 180 or long == -180 or long == 0 then
|
|
long_str = " "
|
|
else
|
|
if long < 0 then
|
|
long_str = "E"
|
|
end
|
|
end
|
|
|
|
lat = math.abs(lat)
|
|
long = 180 - math.abs(long)
|
|
printl("YOU_ARE_SOMEWHERE_NEAR")
|
|
print(" \nLat:" ..lat.." "..lat_str.."\nLong:"..long.." "..long_str.."\n")
|
|
end
|
|
|
|
function use_berry(obj, actor)
|
|
local actor_num = actor.actor_num
|
|
if actor_num == 6 then
|
|
printl("A_MECHANICAL_PERSON_CANT_EAT_BERRIES")
|
|
return
|
|
end
|
|
|
|
play_md_sfx(0x32)
|
|
local berry_type = obj.obj_n - 73 --OBJ_BERRY
|
|
local first_berry = true
|
|
|
|
if (berry_type == 0 and actor_is_affected_by_purple_berries(actor_num))
|
|
or (berry_type == 1 and actor_is_affected_by_green_berries(actor_num))
|
|
or (berry_type == 2 and actor_is_affected_by_brown_berries(actor_num)) then
|
|
printl("YOU_EAT_A_MARTIAN_BERRY_YOU_FEEL_AN_INCREASE_IN_THE_STRANGE")
|
|
else
|
|
printl("YOU_EAT_A_MARTIAN_BERRY_YOU_FEEL_A_STRANGE")
|
|
end
|
|
|
|
if berry_type == 0 then
|
|
printl("RELATIONSHIP_WITH_THINGS_AROUND_YOU")
|
|
actor_increment_purple_berry_count(actor_num)
|
|
elseif berry_type == 1 then
|
|
printl("SENSITIVITY_TO_THE_FEELINGS_OF_OBJECTS_AROUND_YOU")
|
|
actor_increment_green_berry_count(actor_num)
|
|
elseif berry_type == 2 then
|
|
printl("SENSE_OF_YOUR_SPATIAL_LOCATION")
|
|
actor_increment_brown_berry_count(actor_num)
|
|
elseif berry_type == 3 then
|
|
printl("SUDDEN_FLUSH_DIZZINESS_AND_NAUSEA")
|
|
actor.poisoned = false
|
|
Actor.hit(actor, math.random(5, 0x14) + math.random(5, 0x14))
|
|
local counter = actor_get_blue_berry_counter()
|
|
actor_set_blue_berry_counter(counter + math.random(1, 2))
|
|
end
|
|
|
|
if obj.qty == 1 then
|
|
Obj.removeFromEngine(obj)
|
|
else
|
|
obj.qty = obj.qty - 1
|
|
end
|
|
end
|
|
|
|
function use_misc_text(obj)
|
|
|
|
local obj_n = obj.obj_n
|
|
if obj_n == 65 or obj_n == 66 or obj_n == 67 or obj_n == 263 or obj_n == 267 or obj_n == 327 then
|
|
printl("YOU_CANT_DIG_ANY_DEEPER")
|
|
elseif obj_n == 427 then
|
|
printl("IT_IS_STUCK")
|
|
elseif obj_n == 288 then
|
|
printl("THE_CONTROL_PANEL_OPERATES_THE_DREAM_MACHINE")
|
|
elseif obj_n == 199 then
|
|
printl("YOU_NEED_TO_USE_PLIERS_TO_ATTACH_THE_CABLE")
|
|
elseif obj_n == 131 then
|
|
printl("YOU_WILL_CHEW_IT_INSTINCTIVELY")
|
|
elseif obj_n == 184 then
|
|
printl("THE_PLATE_IN_THE_CAMERA_HAS_ALREADY_BEEN_EXPOSED")
|
|
elseif obj_n == 442 or obj_n == 443 or obj_n == 444 then
|
|
printl("YOU_MUST_USE_A_SHOVEL_TO_MOVE_THAT")
|
|
elseif obj_n == 293 then
|
|
printl("YOU_CANT_DETERMINE_HOW_TO_READ_THE_TIME")
|
|
elseif obj_n == 77 or obj_n == 78 then
|
|
printl("THE_BERRIES_ARE_NOT_EDIBLE")
|
|
elseif obj_n == 323 then
|
|
printl("YOU_DONT_KNOW_HOW_IT_WORKS")
|
|
else
|
|
printl("IT_HAS_NO_EFFECT")
|
|
end
|
|
end
|
|
|
|
function get_pile_obj_num(map_tile)
|
|
if (map_tile >= 32 and map_tile <= 36) or map_tile == 12 or map_tile == 13 or (map_tile >= 40 and map_tile <= 63) then
|
|
return 258 --OBJ_DIRT_PILE
|
|
elseif map_tile == 124 or map_tile == 125 or map_tile == 127 then
|
|
return 256 --OBJ_CHUNK_OF_ICE
|
|
end
|
|
|
|
return 0 --CANNOT DIG HERE
|
|
end
|
|
|
|
function get_free_location_around_actor(actor)
|
|
local x_tbl = {-1,0,1,1,1,0,-1,-1}
|
|
local y_tbl = {-1,-1,-1,0,1,1,1,0}
|
|
local pos = {}
|
|
local i
|
|
|
|
pos.z = actor.z
|
|
|
|
for i=1,8 do
|
|
pos.x = actor.x + x_tbl[i]
|
|
pos.y = actor.y + y_tbl[i]
|
|
if map_can_put(pos.x,pos.y,pos.z) == true and map_get_obj(pos.x,pos.y,pos.z) == nil then
|
|
return pos
|
|
end
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
function use_tool_on_ground(obj, target_obj, actor, target_x, target_y, target_z)
|
|
if target_obj ~= nil then
|
|
--check tile flag here.
|
|
printl("THE_GROUND_IS_NOT_CLEAR_FOR_DIGGING")
|
|
return
|
|
end
|
|
|
|
local map_tile = map_get_tile_num(target_x, target_y, target_z)
|
|
|
|
local pile_obj_num = get_pile_obj_num(map_tile)
|
|
|
|
if pile_obj_num == 0 then
|
|
printl("IT_HAS_NO_EFFECT")
|
|
return
|
|
end
|
|
|
|
local hole_obj_num = 257
|
|
|
|
if pile_obj_num == 256 then
|
|
hole_obj_num = 255
|
|
end
|
|
|
|
local hole = Obj.new(hole_obj_num)
|
|
hole.temporary = true
|
|
Obj.moveToMap(hole, target_x, target_y, target_z)
|
|
|
|
local loc = get_free_location_around_actor(actor)
|
|
|
|
if loc ~= nil then
|
|
local pile = Obj.new(pile_obj_num)
|
|
pile.temporary = true
|
|
Obj.moveToMap(pile, loc.x, loc.y, loc.z)
|
|
else
|
|
Obj.removeFromEngine(hole)
|
|
printl("YOU_CANT_DIG_HERE")
|
|
end
|
|
end
|
|
|
|
function use_shovel_on_pile_to_hole(obj, target_obj, to_obj, actor)
|
|
Obj.removeFromEngine(target_obj)
|
|
Obj.removeFromEngine(to_obj)
|
|
|
|
play_md_sfx(0x1b)
|
|
play_md_sfx(0x1b)
|
|
printl("YOU_FILLED_IN_THE_HOLE")
|
|
end
|
|
|
|
function use_shovel_on_ore_to_container(obj, target_obj, to_obj, actor)
|
|
print("\n")
|
|
local ore_quality = get_ore_container_quality(target_obj.obj_n)
|
|
if to_obj.obj_n == 268 then --OBJ_MARTIAN_WHEEL_BARROW
|
|
if to_obj.qty ~= 1 then
|
|
play_md_sfx(0x1b)
|
|
to_obj.qty = 1
|
|
to_obj.quality = ore_quality
|
|
printfl("YOU_PUT_THE_ORE_INTO_THE_WHEELBARROW", target_obj.name)
|
|
Obj.removeFromEngine(target_obj)
|
|
else
|
|
printl("THERE_IS_NO_MORE_ROOM")
|
|
play_md_sfx(5)
|
|
return false
|
|
end
|
|
elseif to_obj.obj_n == 410 then --OBJ_RAIL_CAR
|
|
local qty = to_obj.qty
|
|
if to_obj.qty < 7 then
|
|
if to_obj.qty > 0 and to_obj.quality ~= ore_quality then
|
|
printl("YOU_CANT_MIX_DIFFERENT_THINGS_IN_THE_SAME_LOAD")
|
|
play_md_sfx(5)
|
|
return false
|
|
else
|
|
to_obj.quality = ore_quality
|
|
to_obj.qty = to_obj.qty + 1
|
|
if to_obj.qty == 1 or to_obj.qty == 7 then
|
|
to_obj.frame_n = to_obj.frame_n + 2
|
|
end
|
|
printfl("YOU_PUT_THE_ORE_INTO_THE_RAIL_CAR", target_obj.name)
|
|
Obj.removeFromEngine(target_obj)
|
|
end
|
|
else
|
|
printl("THERE_IS_NO_MORE_ROOM")
|
|
play_md_sfx(5)
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function use_shovel_to_unload_container(obj, target_obj, to_obj, actor)
|
|
if target_obj.qty == 0 then
|
|
printl("THERE_IS_NOTHING_TO_UNLOAD")
|
|
play_md_sfx(5)
|
|
return
|
|
end
|
|
|
|
local ore = Obj.new(get_obj_num_from_ore_quality(target_obj.quality))
|
|
|
|
--FIXME if to_obj == nil do something
|
|
|
|
local success_flag = false
|
|
if to_obj.obj_n == 268 or to_obj.obj_n == 410 then --OBJ_MARTIAN_WHEEL_BARROW
|
|
success_flag = use_shovel_on_ore_to_container(obj, ore, to_obj, actor)
|
|
elseif to_obj.obj_n == 233 then --OBJ_FURNACE
|
|
success_flag = use_shovel_on_ore_to_furnace(obj, ore, to_obj, actor)
|
|
elseif to_obj.obj_n == 257 then --OBJ_HOLE
|
|
--FIXME need to wire up this logic.
|
|
else
|
|
--FIXME need to implement burying logic
|
|
end
|
|
|
|
if success_flag then
|
|
target_obj.qty = target_obj.qty - 1
|
|
if target_obj.obj_n == 410 then --OBJ_RAIL_CAR
|
|
if target_obj.qty == 6 or target_obj.qty == 0 then
|
|
target_obj.frame_n = target_obj.frame_n - 2
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function use_shovel_on_ore_to_furnace(obj, target_obj, to_obj, actor)
|
|
local obj_n = target_obj.obj_n
|
|
|
|
play_md_sfx(0x1b)
|
|
|
|
Obj.removeFromEngine(target_obj)
|
|
if obj_n == 444 then --OBJ_PILE_OF_COAL
|
|
if to_obj.frame_n < 4 then
|
|
activate_power_system()
|
|
end
|
|
else
|
|
printl("IT_HAS_NO_EFFECT")
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function activate_power_system()
|
|
printl("THE_COAL_BEGINS_MOVING_DOWN_THE_BELT")
|
|
Actor.set_talk_flag(0x73, 2)
|
|
Actor.set_talk_flag(0x71, 3)
|
|
activate_power_update_tiles()
|
|
update_conveyor_belt(false)
|
|
end
|
|
|
|
function activate_power_update_tiles()
|
|
anim_play(9)
|
|
anim_play(10)
|
|
anim_play(11)
|
|
anim_play(12)
|
|
local loc = player_get_location()
|
|
for obj in find_obj(loc.z, 208) do --OBJ_CRACK
|
|
if obj ~= nil then
|
|
if map_get_obj(obj.x, obj.y, obj.z, 209) == nil then
|
|
local steam = Obj.new(209, 1)
|
|
Obj.moveToMap(steam, obj.x, obj.y+1, obj.z)
|
|
end
|
|
end
|
|
end
|
|
|
|
for obj in find_obj(loc.z, 233) do --OBJ_FURNACE
|
|
if obj ~= nil then
|
|
local frame_n = obj.frame_n
|
|
if frame_n == 1 or frame_n == 3 then
|
|
obj.frame_n = frame_n + 4
|
|
end
|
|
end
|
|
end
|
|
|
|
for obj in find_obj(loc.z, 154) do --OBJ_LAMP
|
|
if obj ~= nil then
|
|
obj.frame_n = 1
|
|
end
|
|
end
|
|
for obj in find_obj(4, 154) do --OBJ_LAMP
|
|
if obj ~= nil then
|
|
obj.frame_n = 1
|
|
end
|
|
end
|
|
end
|
|
|
|
function shutdown_power_update_tiles()
|
|
anim_stop(9)
|
|
anim_stop(10)
|
|
anim_stop(11)
|
|
anim_stop(12)
|
|
local loc = player_get_location()
|
|
for obj in find_obj(loc.z, 209) do --OBJ_STEAM_LEAK
|
|
if obj ~= nil then
|
|
Obj.removeFromEngine(obj)
|
|
end
|
|
end
|
|
|
|
for obj in find_obj(loc.z, 233) do --OBJ_FURNACE
|
|
if obj ~= nil then
|
|
local frame_n = obj.frame_n
|
|
if frame_n == 5 or frame_n == 7 then
|
|
obj.frame_n = frame_n - 4
|
|
end
|
|
end
|
|
end
|
|
|
|
for obj in find_obj(loc.z, 154) do --OBJ_LAMP
|
|
if obj ~= nil then
|
|
obj.frame_n = 0
|
|
end
|
|
end
|
|
for obj in find_obj(4, 154) do --OBJ_LAMP
|
|
if obj ~= nil then
|
|
obj.frame_n = 0
|
|
end
|
|
end
|
|
end
|
|
|
|
function update_conveyor_belt(can_stop)
|
|
if Actor.get_talk_flag(0x73, 2) == false then
|
|
return
|
|
end
|
|
local player_loc = player_get_location()
|
|
|
|
if player_loc.z ~= 5 then
|
|
return
|
|
end
|
|
|
|
--NOTE. The original game used generalised logic to search for conveyors.
|
|
-- I haven't used that here as there is only one conveyor in the game.
|
|
|
|
local x = 0x3c
|
|
local y = 0x63
|
|
local z = 5
|
|
|
|
local conveyor = map_get_obj(x, y, z, 188) --OBJ_CONVEYOR_BELT
|
|
|
|
while conveyor ~= nil do
|
|
if conveyor.frame_n == 2 then
|
|
local seam = map_get_obj(x, y, z, 189) --OBJ_CONVEYOR_BELT1
|
|
if seam ~= nil then
|
|
Obj.removeFromEngine(seam)
|
|
end
|
|
elseif conveyor.frame_n == 0 then
|
|
if conveyor.qty == 0 then
|
|
local seam = Obj.new(189)
|
|
Obj.moveToMap(seam, x, y, z)
|
|
conveyor.qty = 4
|
|
end
|
|
conveyor.qty = conveyor.qty - 1
|
|
end
|
|
|
|
local seam = map_get_obj(x, y, z, 189) --OBJ_CONVEYOR_BELT1
|
|
if seam ~= nil then
|
|
seam.x = seam.x + 1
|
|
end
|
|
|
|
for obj in objs_at_loc(x, y, z) do
|
|
if obj.obj_n == 447 or obj.weight > 0 then --OBJ_HUGE_LUMP_OF_COAL
|
|
obj.x = obj.x + 1
|
|
end
|
|
end
|
|
|
|
local actor = map_get_actor(x, y, z)
|
|
if actor ~= nil then
|
|
Actor.move(actor, x+1, y, z)
|
|
end
|
|
|
|
x = x - 1
|
|
conveyor = map_get_obj(x, y, z, 188) --OBJ_CONVEYOR_BELT
|
|
end
|
|
|
|
|
|
if can_stop and Actor.get_talk_flag(0x71, 3) then
|
|
if math.random(0, 6) == 0 then
|
|
printl("THE_CONVEYOR_BELT_STOPS")
|
|
Actor.clear_talk_flag(0x73, 2)
|
|
Actor.clear_talk_flag(0x71, 3)
|
|
shutdown_power_update_tiles()
|
|
end
|
|
end
|
|
|
|
|
|
end
|
|
|
|
function midgame_cutscene_2()
|
|
play_midgame_sequence(2)
|
|
|
|
for tower in find_obj(0, 201) do --OBJ_TOWER_TOP
|
|
if tower.x >= 0x3d0 and tower.x <= 0x3f0 and tower.y >= 0x1d0 and tower.y <= 0x1e7 then
|
|
tower.frame_n = 4 + (tower.frame_n % 4)
|
|
end
|
|
end
|
|
|
|
for cable in find_obj(0, 214) do --OBJ_POWER_CABLE
|
|
if cable.x >= 0x3d0 and cable.x <= 0x3f0 and cable.y >= 0x1d0 and cable.y <= 0x1e7 then
|
|
cable.obj_n = 215
|
|
end
|
|
end
|
|
end
|
|
|
|
function use_fixed_belt_on_bare_rollers(obj, target_obj, actor)
|
|
local start_obj = nil
|
|
local rollers = target_obj
|
|
while rollers ~= nil do
|
|
if rollers.frame_n == 0 then
|
|
start_obj = rollers
|
|
break
|
|
end
|
|
rollers = map_get_obj(rollers.x-1,rollers.y,rollers.z, rollers.obj_n)
|
|
end
|
|
|
|
if start_obj == nil then
|
|
printl("OOOPS_THESE_ROLLERS_CAN_NEVER_BE_FIXED")
|
|
return
|
|
end
|
|
|
|
rollers = start_obj
|
|
local i = 4
|
|
while rollers ~= nil do
|
|
rollers.obj_n = 188
|
|
if i == 0 then
|
|
i = 4
|
|
local belt_join_obj = Obj.new(189)
|
|
Obj.moveToMap(belt_join_obj, rollers.x, rollers.y, rollers.z)
|
|
else
|
|
i = i - 1
|
|
end
|
|
rollers = map_get_obj(rollers.x+1,rollers.y,rollers.z, 192) --OBJ_BARE_ROLLERS
|
|
end
|
|
|
|
Obj.removeFromEngine(obj)
|
|
Actor.set_talk_flag(0x72, 2)
|
|
end
|
|
|
|
function use_ruby_slippers(obj, actor)
|
|
if obj.readied == false then
|
|
--FIXME check that we can ready this object.
|
|
Obj.removeFromEngine(obj)
|
|
Actor.inv_ready_obj(actor, obj)
|
|
return
|
|
end
|
|
|
|
if obj.quality == 2 then
|
|
printl("YOU_MAY_USE_THE_RUBY_SLIPPERS_TO_GO_HOME")
|
|
local input = input_select("yn", false)
|
|
if input == "Y" then
|
|
play_end_sequence()
|
|
else
|
|
play_midgame_sequence(13)
|
|
end
|
|
else
|
|
printl("CLICK")
|
|
obj.quality = obj.quality + 1
|
|
end
|
|
end
|
|
|
|
function foes_are_nearby()
|
|
local loc = player_get_location()
|
|
local i
|
|
for i=1,0xff do
|
|
local actor = Actor.get(i)
|
|
if actor.alive and (actor.align == ALIGNMENT_EVIL or actor.align == ALIGNMENT_CHAOTIC) and actor.z == loc.z then
|
|
if get_wrapped_dist(actor.x, loc.x) < 40 and get_wrapped_dist(actor.y, loc.y) < 40 then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function is_target_visible_to_actor(actor, target)
|
|
--FIXME
|
|
return true
|
|
end
|
|
|
|
function npcs_are_nearby()
|
|
local loc = player_get_location()
|
|
local i
|
|
local player = Actor.get_player_actor()
|
|
for i=1,0xff do
|
|
local actor = Actor.get(i)
|
|
if actor.alive and actor.asleep == false and actor.in_party == false and actor.z == loc.z then
|
|
if get_wrapped_dist(actor.x, loc.x) < 6 and get_wrapped_dist(actor.y, loc.y) < 6 and is_target_visible_to_actor(player, actor) then
|
|
return actor
|
|
end
|
|
end
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
function is_actor_able_to_talk_to_player(actor)
|
|
local player = Actor.get_player_actor()
|
|
local loc = player_get_location()
|
|
if actor.alive and actor.asleep == false and actor.z == loc.z then
|
|
if get_wrapped_dist(actor.x, loc.x) < 6 and get_wrapped_dist(actor.y, loc.y) < 6 and is_target_visible_to_actor(player, actor) then
|
|
return true
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function rest_heal_party(hours_to_rest)
|
|
local actor
|
|
for actor in party_members() do
|
|
local hp = math.random(3,8) + math.random(3,8) * math.floor(hours_to_rest / 2)
|
|
local max_hp = actor_get_max_hp(actor)
|
|
if actor.hp + hp > max_hp then
|
|
actor.hp = max_hp
|
|
else
|
|
actor.hp = actor.hp + hp
|
|
end
|
|
end
|
|
end
|
|
|
|
function rest_level_up_actor(actor)
|
|
if actor.actor_num > 15 then
|
|
return
|
|
end
|
|
|
|
local exp_level_tbl = {
|
|
[0] = 0,
|
|
[1] = 100,
|
|
[2] = 200,
|
|
[3] = 400,
|
|
[4] = 800,
|
|
[5] = 1600,
|
|
[6] = 3200,
|
|
[7] = 6400,
|
|
[8] = 32767,
|
|
}
|
|
|
|
if actor.exp <= exp_level_tbl[actor.level] then
|
|
return
|
|
end
|
|
|
|
actor.level = actor.level + 1
|
|
|
|
local max_hp = actor_get_max_hp(actor)
|
|
if actor.hp + 30 > max_hp then
|
|
actor.hp = max_hp
|
|
else
|
|
actor.hp = actor.hp + 30
|
|
end
|
|
|
|
Actor.show_portrait(actor)
|
|
|
|
local obj_n = actor.obj_n
|
|
local gender = math.random(0,1)
|
|
if obj_n == 342 or obj_n == 343 or obj_n == 345 or (obj_n >= 347 and obj_n <= 353) then
|
|
gender = 0
|
|
elseif obj_n == 344 or obj_n == 346 or (obj_n >= 354 and obj_n <= 357) then
|
|
gender = 1
|
|
end
|
|
|
|
local gender_pronoun = "He"
|
|
if gender == 1 then
|
|
gender_pronoun = "She"
|
|
end
|
|
|
|
printfl("HAS_A_DREAM", actor.name)
|
|
printfl("SEES_THREE_STONE_OBELISKS", gender_pronoun)
|
|
printfl("FEELS_DRAWN_TO_ONE_OF_THE_OBELISKS", gender_pronoun)
|
|
printfl("DOES_TOUCH_THE_OBELISK", actor.name)
|
|
printl("WHICH_BHS")
|
|
|
|
local answer = input_select("bhs", false)
|
|
|
|
if answer == "B" then
|
|
if actor.int < 30 then
|
|
actor.int = actor.int + 1
|
|
end
|
|
elseif answer == "H" then
|
|
if actor.dex < 30 then
|
|
actor.dex = actor.dex + 1
|
|
end
|
|
elseif answer == "S" then
|
|
if actor.str < 30 then
|
|
actor.str = actor.str + 1
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
function use_tent(obj, actor)
|
|
if player_is_in_solo_mode() then
|
|
printl("NOT_WHILE_IN_SOLO_MODE")
|
|
play_md_sfx(5)
|
|
return
|
|
end
|
|
|
|
if g_in_dream_mode then
|
|
printl("YOU_CANT_SLEEP_IN_A_DREAM")
|
|
play_md_sfx(5)
|
|
return
|
|
end
|
|
|
|
local tent_loc = {}
|
|
|
|
if obj.on_map then
|
|
tent_loc.x = obj.x
|
|
tent_loc.y = obj.y
|
|
tent_loc.z = obj.z
|
|
else
|
|
tent_loc = player_get_location()
|
|
end
|
|
|
|
local x, y
|
|
|
|
for y = tent_loc.y - 2, tent_loc.y do
|
|
for x = tent_loc.x - 1, tent_loc.x + 1 do
|
|
local map_obj = map_get_obj(x,y,tent_loc.z)
|
|
if map_obj ~= nil and map_obj.obj_n ~= 106 then
|
|
if tile_get_flag(map_obj.tile_num, 3, 4) == false then
|
|
printfl("TENT_OBJ_IN_THE_WAY", map_obj.name)
|
|
play_md_sfx(5)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for y = tent_loc.y - 2, tent_loc.y do
|
|
for x = tent_loc.x - 1, tent_loc.x + 1 do
|
|
if tile_get_flag(map_get_tile_num(x,y,tent_loc.z), 1, 1) == true then --if map tile is impassible
|
|
printl("THE_GROUND_IS_NOT_FLAT_ENOUGH")
|
|
play_md_sfx(5)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
printl("REST")
|
|
|
|
if party_is_in_combat_mode() then
|
|
print(" - ")
|
|
printl("NOT_WHILE_IN_COMBAT_MODE")
|
|
play_md_sfx(5)
|
|
return
|
|
end
|
|
|
|
if foes_are_nearby() then
|
|
printl("NOT_WHILE_FOES_ARE_NEAR")
|
|
play_md_sfx(5)
|
|
return
|
|
end
|
|
|
|
local npc = npcs_are_nearby()
|
|
if npc ~= nil then
|
|
printfl("IS_TOO_NEAR_TO_SETUP_CAMP", npc.name)
|
|
play_md_sfx(5)
|
|
return
|
|
end
|
|
|
|
--poison check
|
|
|
|
local actor
|
|
local poisoned = false
|
|
for actor in party_members() do
|
|
if actor.poisoned then
|
|
poisoned = true
|
|
printfl("IS_POISONED", actor.name)
|
|
end
|
|
end
|
|
|
|
if poisoned then
|
|
printl("DO_YOU_REALLY_WANT_TO_SLEEP")
|
|
local answer = input_select("yn", false)
|
|
if answer == "N" or answer == "n" then
|
|
return
|
|
end
|
|
end
|
|
|
|
local party_is_using_berries = false
|
|
for actor in party_members() do
|
|
local actor_num = actor.actor_num
|
|
local green = actor_is_affected_by_green_berries(actor_num)
|
|
local brown = actor_is_affected_by_brown_berries(actor_num)
|
|
|
|
if brown or green then
|
|
party_is_using_berries = true
|
|
if brown and green then
|
|
printfl("COMPLAINS_OF_TOO_MUCH_LIGHT_AND_INANIMATE", actor.name)
|
|
elseif brown then
|
|
printfl("COMPLAINS_OF_TOO_MUCH_LIGHT", actor.name)
|
|
else --green
|
|
printfl("COMPLAINS_OF_INANIMATE_THINGS_TALKING", actor.name)
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
if party_is_using_berries then
|
|
if party_get_size() == 1 then
|
|
printl("YOU_CANT_SLEEP")
|
|
else
|
|
printl("NOBODY_CAN_SLEEP")
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
local player = Actor.get_player_actor()
|
|
player.x = tent_loc.x
|
|
player.y = tent_loc.y
|
|
|
|
local tent = Obj.new(134, 3)
|
|
Obj.moveToMap(tent, player.x, player.y-1, player.z)
|
|
|
|
tent = Obj.new(134, 5)
|
|
Obj.moveToMap(tent, player.x+1, player.y-1, player.z)
|
|
|
|
tent = Obj.new(134, 6)
|
|
Obj.moveToMap(tent, player.x-1, player.y, player.z)
|
|
|
|
tent = Obj.new(134, 9)
|
|
Obj.moveToMap(tent, player.x+1, player.y, player.z)
|
|
|
|
tent = Obj.new(134, 8)
|
|
Obj.moveToMap(tent, player.x, player.y, player.z)
|
|
|
|
party_move(player.x, player.y, player.z)
|
|
|
|
script_wait(500)
|
|
|
|
party_hide_all()
|
|
|
|
tent.frame_n = 7
|
|
|
|
local hour = clock_get_hour()
|
|
local time
|
|
local hours_to_rest
|
|
|
|
if hour < 7 or hour > 16 then
|
|
time = i18n("SUNRISE")
|
|
if hour < 7 then
|
|
hours_to_rest = 7 - hour
|
|
else
|
|
hours_to_rest = 24 - hour + 7
|
|
end
|
|
elseif hour <= 16 then
|
|
time = i18n("SUNSET")
|
|
hours_to_rest = 18 - hour
|
|
end
|
|
|
|
printfl("REST_UNTIL", time)
|
|
local answer = input_select("yn", false)
|
|
|
|
if answer == "N" or answer == "n" then
|
|
printl("HOW_MANY_HOURS")
|
|
hours_to_rest = input_select_integer("0123456789", true)
|
|
end
|
|
|
|
g_party_is_warm = true
|
|
|
|
if g_hours_till_next_healing == 0 and hours_to_rest > 4 then
|
|
rest_heal_party(hours_to_rest)
|
|
g_hours_till_next_healing = 6
|
|
end
|
|
|
|
local can_level_up = false
|
|
if hours_to_rest * 3 > party_get_size() then
|
|
can_level_up = true
|
|
end
|
|
|
|
local i
|
|
for i=0,hours_to_rest*3-1 do
|
|
advance_time(20)
|
|
script_wait(100)
|
|
if i < party_get_size() then
|
|
local actor = party_get_member(i)
|
|
rest_level_up_actor(actor)
|
|
end
|
|
end
|
|
|
|
local actor
|
|
local poisoned = false
|
|
for actor in party_members() do
|
|
if actor.poisoned then
|
|
if math.random(1, 8) + math.random(1, 8) >= 15 then
|
|
actor.poisoned = false
|
|
printfl("FEELS_BETTER", actor.name)
|
|
else
|
|
if actor.hp < hours_to_rest * 2 + 5 then
|
|
actor.hp = 5
|
|
else
|
|
actor.hp = actor.hp - (hours_to_rest * 2 + 5)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
tent.frame_n = 8 --Open the tent flap
|
|
party_show_all()
|
|
|
|
party_move(player.x, player.y + 1, player.z)
|
|
|
|
script_wait(500)
|
|
|
|
--remove tent from map
|
|
local z = player.z
|
|
for tent in find_obj(z, 134) do
|
|
if tent ~= nil and
|
|
((tent.x == tent_loc.x and tent.y == tent_loc.y-1) or
|
|
(tent.x == wrap_coord(tent_loc.x+1,z) and tent.y == tent_loc.y-1) or
|
|
(tent.x == wrap_coord(tent_loc.x-1,z) and tent.y == tent_loc.y) or
|
|
(tent.x == wrap_coord(tent_loc.x+1,z) and tent.y == tent_loc.y) or
|
|
(tent.x == tent_loc.x and tent.y == tent_loc.y))
|
|
then
|
|
Obj.removeFromEngine(tent)
|
|
end
|
|
end
|
|
|
|
g_party_is_warm = false
|
|
end
|
|
|
|
function use_red_berry(obj, actor)
|
|
if not party_is_in_combat_mode() then
|
|
printl("THAT_WOULD_BE_A_WASTE_OUTSIDE_OF_COMBAT")
|
|
return
|
|
end
|
|
|
|
if actor.frenzy == false then
|
|
printfl("ENTERS_A_BATTLE_FRENZY", actor.name)
|
|
play_md_sfx(0x32)
|
|
end
|
|
|
|
actor.frenzy = true
|
|
|
|
local qty = obj.qty
|
|
|
|
if qty > 1 then
|
|
obj.qty = qty - 1
|
|
else
|
|
Obj.removeFromEngine(obj)
|
|
end
|
|
end
|
|
|
|
function use_spittoon(obj, actor)
|
|
if not actor.hypoxia then
|
|
printl("YOU_SPIT_INTO_THE_SPITTOON")
|
|
else
|
|
printl("YOUR_MOUTH_IS_TOO_DRY")
|
|
end
|
|
end
|
|
|
|
function use_gong(obj, target_obj, actor)
|
|
printl("GONG")
|
|
play_md_sfx(0xf)
|
|
end
|
|
|
|
function use_musical_instrument(obj, actor)
|
|
|
|
local obj_n = obj.obj_n
|
|
|
|
if obj_n == 280 then --OBJ_CYMBALS
|
|
printl("CHING")
|
|
play_md_sfx(0x36)
|
|
elseif obj_n == 281 then --OBJ_TAMBORINE
|
|
printl("SHING")
|
|
play_md_sfx(0x35)
|
|
elseif obj_n == 282 then --OBJ_DRUM
|
|
printl("THUMP_THUMP")
|
|
play_md_sfx(0x34)
|
|
script_wait(100)
|
|
play_md_sfx(0x34)
|
|
elseif obj_n == 283 then --OBJ_ACCORDION
|
|
printl("WHEEEEZE")
|
|
play_md_sfx(0x37)
|
|
else
|
|
printfl("YOU_PLAY_THE", obj.name)
|
|
end
|
|
end
|
|
|
|
function use_wrench_on_switchbar(obj, target_obj, actor)
|
|
if target_obj.quality == 1 then
|
|
if target_obj.on_map then
|
|
local turntable = map_get_obj(target_obj.x-1, target_obj.y-1, target_obj.z, 413)
|
|
if turntable ~= nil then
|
|
target_obj.frame_n = turntable.frame_n
|
|
target_obj.quality = 0
|
|
printl("THE_SWITCH_IS_FASTENED")
|
|
play_md_sfx(0x1f)
|
|
return
|
|
end
|
|
end
|
|
printl("THIS_SWITCH_CANNOT_BE_FIXED")
|
|
play_md_sfx(0x5)
|
|
else
|
|
printl("THE_SWITCH_IS_LOOSE")
|
|
play_md_sfx(0x1f)
|
|
target_obj.quality = 1
|
|
end
|
|
end
|
|
|
|
function use_wrench_on_drill(obj, target_obj, actor)
|
|
local drill_cart
|
|
if target_obj.on_map then
|
|
drill_cart = map_get_obj(target_obj.x, target_obj.y, target_obj.z, 439)
|
|
end
|
|
|
|
if drill_cart ~= nil then
|
|
local drill = Obj.new(441,1) --assembled drill
|
|
Obj.moveToMap(drill, target_obj.x, target_obj.y, target_obj.z)
|
|
Obj.removeFromEngine(target_obj)
|
|
Obj.removeFromEngine(drill_cart)
|
|
printl("THE_DRILLS_POWER_IS_CONNECTED")
|
|
play_md_sfx(0x1f)
|
|
else
|
|
printl("THE_DRILL_MUST_BE_INSTALLED_ONTO_A_DRILL_CART")
|
|
end
|
|
end
|
|
|
|
function use_wrench_on_panel(obj, target_obj, actor)
|
|
if target_obj.on_map == false then
|
|
printl("IT_HAS_NO_EFFECT")
|
|
return
|
|
end
|
|
|
|
local quality = target_obj.quality
|
|
local panel_qty = target_obj.qty
|
|
if quality == 0 then
|
|
target_obj.quality = 1
|
|
printl("THE_PANEL_IS_LOOSE")
|
|
play_md_sfx(0x1f)
|
|
elseif bit32.btest(quality, 2) then
|
|
printl("IT_MUST_BE_REPAIRED_FIRST")
|
|
play_md_sfx(0x5)
|
|
else
|
|
local cabinet = map_get_obj(target_obj.x, target_obj.y, target_obj.z, 457)
|
|
if cabinet == nil then
|
|
printl("PANELS_ARE_ONLY_INSTALLED_ONTO_CABINETS")
|
|
play_md_sfx(0x5)
|
|
else
|
|
quality = cabinet.quality
|
|
if (quality == 0 and panel_qty ~= 0) or
|
|
(quality ~= 0 and quality <= 3 and panel_qty == 0 and target_obj.frame_n ~= (quality - 1) ) or
|
|
(quality ~= 0 and (quality > 3 or panel_qty ~= 0) and quality ~= panel_qty) then
|
|
printl("THIS_CABINET_REQUIRES_A_DIFFERENT_TYPE_OF_PANEL")
|
|
play_md_sfx(0x5)
|
|
else
|
|
target_obj.quality = target_obj.quality - 1
|
|
printl("THE_PANEL_IS_FASTENED")
|
|
play_md_sfx(0x1f)
|
|
if target_obj.quality == 3 then
|
|
Actor.set_talk_flag(0x74, 3)
|
|
if Actor.get_talk_flag(0x74, 0) then
|
|
Actor.set_talk_flag(0x60, 2)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
function use_oxium_bin(obj, actor)
|
|
if map_can_reach_point (actor.x, actor.y, obj.x, obj.y, obj.z) == false then
|
|
printl("BLOCKED")
|
|
return
|
|
end
|
|
|
|
local oxium = Obj.new(131) --OBJ_BLOB_OF_OXIUM
|
|
oxium.qty = 20
|
|
|
|
if Actor.can_carry_obj(actor, oxium) then
|
|
Actor.inv_add_obj(actor, oxium, STACK_OBJECT_QTY)
|
|
printl("YOU_GET_TWO_HANDFULS_OF_OXIUM_FROM_THE_BIN")
|
|
Actor.set_talk_flag(0x12, 4)
|
|
else
|
|
printl("YOU_ARE_CARRYING_TOO_MUCH_ALREADY")
|
|
end
|
|
end
|
|
|
|
function use_sledge_hammer_on_replacement_track_to_broken_track(obj, target_obj, to_obj, actor)
|
|
play_md_sfx(0x20)
|
|
printl("WHICH_SECTION_OF_RAIL_NEEDS_FIXING")
|
|
Obj.removeFromEngine(target_obj)
|
|
to_obj.obj_n = 414 --OBJ_TRACK
|
|
end
|
|
|
|
function use_pliers_on_spool_to_tower(obj, target_obj, to_obj, actor)
|
|
|
|
if actor_find_max_wrapped_xy_distance(actor, to_obj.x, to_obj.y) > 1 then
|
|
printl("THE_WORK_IS_TO_PRECISE_TO_PERFORM_TELEKINETICALLY")
|
|
return
|
|
end
|
|
|
|
if Actor.get_talk_flag(0x73, 2) == false or Actor.get_talk_flag(0x71, 3) == true then
|
|
printl("THE_CABLE_DOES_NOT_NEED_REPLACEMENT")
|
|
return
|
|
end
|
|
|
|
if actor_is_holding_obj(actor, 38) == false then --OBJ_RUBBER_GLOVES
|
|
Actor.hit(actor, math.random(0, math.floor(actor.max_hp/2)))
|
|
local spector = Actor.get(2)
|
|
if is_actor_able_to_talk_to_player(spector) then
|
|
Actor.set_talk_flag(spector, 2)
|
|
Actor.talk(spector)
|
|
end
|
|
else
|
|
play_md_sfx(0x1f)
|
|
Obj.removeFromEngine(target_obj)
|
|
Actor.set_talk_flag(0x73, 4)
|
|
play_midgame_sequence(3)
|
|
for obj in find_obj_from_area(0x3d0, 0x1d0, 0, 32, 17) do
|
|
if obj.obj_n == 215 then -- OBJ_POWER_CABLE1
|
|
obj.obj_n = 214 -- OBJ_POWER_CABLE
|
|
end
|
|
end
|
|
|
|
for obj in find_obj(0, 315) do --OBJ_CHAMBER1
|
|
Obj.removeFromEngine(obj)
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
function use_gate(obj, actor)
|
|
if bit32.btest(obj.quality, 128) == true then
|
|
printl("IT_IS_APPARENTLY_LOCKED")
|
|
return
|
|
end
|
|
|
|
local frame_n = obj.frame_n
|
|
if frame_n == 0 or frame_n == 1 then
|
|
obj.frame_n = 3
|
|
obj.x = obj.x - 1
|
|
elseif frame_n == 2 or frame_n == 3 then
|
|
obj.frame_n = 1
|
|
obj.x = obj.x + 1
|
|
elseif frame_n == 4 or frame_n == 5 then
|
|
obj.frame_n = 7
|
|
elseif frame_n == 6 or frame_n == 7 then
|
|
obj.frame_n = 5
|
|
end
|
|
|
|
|
|
end
|
|
|
|
function use_switch_bar(obj, actor)
|
|
if obj.frame_n == 0 then
|
|
obj.frame_n = 1
|
|
else
|
|
obj.frame_n = 0
|
|
end
|
|
|
|
if obj.on_map == false or map_get_obj(obj.x-1,obj.y-1,obj.z, 413) == nil then
|
|
printl("IT_HAS_NO_EFFECT")
|
|
return
|
|
end
|
|
|
|
if obj.quality == 1 then
|
|
printl("IT_TURNS_LOOSELY")
|
|
return
|
|
end
|
|
|
|
local turntable = map_get_obj(obj.x-1,obj.y-1,obj.z, 413)
|
|
turntable.frame_n = obj.frame_n
|
|
|
|
local railcar = map_get_obj(obj.x-1,obj.y-1,obj.z, 410)
|
|
if railcar ~= nil then
|
|
railcar.frame_n = railcar.frame_n - (railcar.frame_n % 2)
|
|
railcar.frame_n = railcar.frame_n + turntable.frame_n
|
|
end
|
|
end
|
|
|
|
function use_reading_material(obj, actor)
|
|
if obj.quality == 0 then
|
|
local signatures = ""
|
|
if Actor.get_talk_flag(5, 3) == true then
|
|
signatures = signatures .. " Richard Sherman"
|
|
end
|
|
signatures = signatures .. "\n"
|
|
|
|
if Actor.get_talk_flag(0x19, 3) == true then
|
|
signatures = signatures .. " Capt. Gregory Duprey"
|
|
end
|
|
signatures = signatures .. "\n"
|
|
|
|
if Actor.get_talk_flag(0x1a, 3) == true then
|
|
signatures = signatures .. " Doctor David Yellin"
|
|
end
|
|
signatures = signatures .. "\n"
|
|
|
|
display_text_in_scroll_gump(i18nf("AFFIDAVIT", player_get_name(), signatures))
|
|
else
|
|
local text = load_text_from_lzc("mdtext.lzc", obj.quality - 1)
|
|
if text ~= nil then
|
|
display_text_in_scroll_gump(text)
|
|
else
|
|
printl("YOU_CANT_READ_IT")
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
function use_pool_table(obj, actor)
|
|
if Actor.inv_get_readied_obj_n(actor, ARM) ~= 401 then --OBJ_POOL_CUE
|
|
printl("YOU_NEED_A_POOL_CUE")
|
|
return
|
|
end
|
|
local pool_table1 = map_get_obj(wrap_coord(obj.x - 1, obj.z), obj.y, obj.z, 400) -- OBJ_UNK_400
|
|
local rand = math.random
|
|
if pool_table1 == nil then
|
|
pool_table1 = Obj.new(400, rand(0, 6))
|
|
Obj.moveToMap(pool_table1, wrap_coord(obj.x - 1, obj.z), obj.y, obj.z)
|
|
end
|
|
|
|
local pool_table2 = map_get_obj(obj.x, obj.y, obj.z, 400) -- OBJ_UNK_400
|
|
if pool_table2 == nil then
|
|
pool_table2 = Obj.new(400, rand(0, 6))
|
|
Obj.moveToMap(pool_table2, wrap_coord(obj.x - 1, obj.z), obj.y, obj.z)
|
|
end
|
|
|
|
for i=1,10 do
|
|
if i~= 1 then
|
|
script_wait(rand(200,500))
|
|
end
|
|
play_md_sfx(0x1c + rand(0, 2))
|
|
script_wait(rand(10,200))
|
|
play_md_sfx(0x1c + rand(0, 2))
|
|
|
|
pool_table1.frame_n = rand(0, 6)
|
|
pool_table2.frame_n = rand(0, 6)
|
|
|
|
if rand(0, 40) >= actor_dex_adj(actor) then
|
|
break
|
|
end
|
|
end
|
|
|
|
if rand(0, 40) < actor_dex_adj(actor) then
|
|
printl("GOOD_SHOT_OLD_BEAN")
|
|
end
|
|
end
|
|
|
|
function use_ready_obj(obj, actor)
|
|
if not Actor.can_carry_obj(actor, obj) then
|
|
printl("YOU_ARE_CARRYING_TOO_MUCH_ALREADY")
|
|
return
|
|
end
|
|
if obj.readied == true then
|
|
return
|
|
end
|
|
|
|
Obj.removeFromEngine(obj)
|
|
Obj.moveToInv(obj, actor.actor_num)
|
|
|
|
Actor.inv_ready_obj(actor, obj)
|
|
end
|
|
|
|
function use_heartstone_on_metal_woman(obj, target_obj, actor)
|
|
if target_obj.quality == 1 then
|
|
printl("THE_ROBOT_ALREADY_HAS_A_HEARTSTONE")
|
|
else
|
|
target_obj.quality = 1
|
|
Obj.removeFromEngine(obj)
|
|
play_md_sfx(0x1f)
|
|
printl("THE_HEARTSTONE_IS_INSTALLED")
|
|
end
|
|
|
|
end
|
|
|
|
function use_manuscript_on_mailbox(obj, target_obj, actor)
|
|
local twain = Actor.get(0x57)
|
|
|
|
finish_dream_quest(twain)
|
|
Actor.set_talk_flag(twain, 6)
|
|
Actor.talk(twain)
|
|
wake_from_dream()
|
|
end
|
|
|
|
function use_assembled_drill(obj, actor)
|
|
|
|
play_md_sfx(0x10)
|
|
|
|
local x = obj.x
|
|
local y = obj.y
|
|
local z = obj.z
|
|
|
|
if obj.frame_n == 1 then
|
|
x = x - 1
|
|
elseif obj.frame_n == 3 then
|
|
y = y - 1
|
|
elseif obj.frame_n == 4 then
|
|
y = y + 1
|
|
else
|
|
x = x + 1
|
|
end
|
|
|
|
local target_obj
|
|
for obj in objs_at_loc(x, y, z) do
|
|
if obj.obj_n == 445 --OBJ_IRON_ORE
|
|
or obj.obj_n == 446 -- OBJ_VEIN_OF_COAL
|
|
or obj.obj_n == 213 then --OBJ_CAVE_IN
|
|
target_obj = obj
|
|
break
|
|
end
|
|
end
|
|
|
|
if target_obj == nil then
|
|
target_obj = map_get_obj(x, y, z, 213, true)
|
|
end
|
|
|
|
local drilled_matterial
|
|
|
|
if target_obj == nil then
|
|
if can_drill_at_loc(x, y, z) == true then
|
|
drilled_matterial = 442 --OBJ_PILE_OF_ROCKS
|
|
else
|
|
local target_actor = map_get_actor(x, y, z)
|
|
if target_actor ~= nil then
|
|
--FIXME attack actor here. 40 points of damage
|
|
else
|
|
printl("THERE_IS_NOTHING_TO_DRILL_INTO")
|
|
end
|
|
return
|
|
end
|
|
elseif target_obj.obj_n == 445 then --OBJ_IRON_ORE
|
|
drilled_matterial = 443 --OBJ_PILE_OF_IRON_ORE
|
|
elseif target_obj.obj_n == 446 then --OBJ_VEIN_OF_COAL
|
|
drilled_matterial = 444 --OBJ_PILE_OF_COAL
|
|
end
|
|
|
|
if drilled_matterial ~= nil then
|
|
local spoil_location = get_free_location_around_drill(obj)
|
|
if spoil_location ~= nil then
|
|
local spoil_obj = Obj.new(drilled_matterial)
|
|
Obj.moveToMap(spoil_obj, spoil_location)
|
|
else
|
|
printl("THERE_IS_NO_ROOM_LEFT_FOR_THE_ORE")
|
|
end
|
|
end
|
|
|
|
if target_obj then
|
|
if target_obj.quality > 1 then
|
|
target_obj.quality = target_obj.quality - 1
|
|
else
|
|
Obj.removeFromEngine(target_obj)
|
|
end
|
|
end
|
|
|
|
if drilled_matterial == nil then
|
|
Obj.removeFromEngine(target_obj)
|
|
end
|
|
|
|
end
|
|
|
|
function get_free_location_around_drill(drill)
|
|
local x_tbl = {-1,0,1,1,1,0,-1,-1}
|
|
local y_tbl = {-1,-1,-1,0,1,1,1,0}
|
|
local pos = {}
|
|
local i
|
|
|
|
pos.z = drill.z
|
|
|
|
for i=1,8 do
|
|
pos.x = drill.x + x_tbl[i]
|
|
pos.y = drill.y + y_tbl[i]
|
|
local obj = map_get_obj(pos.x, pos.y, pos.z)
|
|
if obj == nil or is_blood(obj.obj_num) then
|
|
if tile_get_flag(map_get_tile_num(pos), 1, 1) == false then --not blocked.
|
|
return pos
|
|
end
|
|
end
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
function get_ore_container_quality(ore_obj_num)
|
|
local tbl = {[258]=1,[442]=2,[443]=3,[444]=4} --OBJ_DIRT_PILE, OBJ_PILE_OF_ROCKS, OBJ_PILE_OF_IRON_ORE, OBJ_PILE_OF_COAL
|
|
local quality = tbl[ore_obj_num]
|
|
if quality == nil then
|
|
quality = 1
|
|
end
|
|
|
|
return quality
|
|
end
|
|
|
|
function get_obj_num_from_ore_quality(ore_quality)
|
|
if ore_quality == 2 then
|
|
return 442 --OBJ_PILE_OF_ROCKS
|
|
elseif ore_quality == 3 then
|
|
return 443 --OBJ_PILE_OF_IRON_ORE
|
|
elseif ore_quality == 4 then
|
|
return 444 --OBJ_PILE_OF_COAL
|
|
end
|
|
|
|
return 258 --OBJ_DIRT_PILE
|
|
end
|
|
|
|
function can_drill_at_loc(x,y,z)
|
|
local tile_num = map_get_tile_num(x, y, z)
|
|
|
|
if tile_num >= 0xf0 and tile_num <= 0xfb then
|
|
return true
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
local use_shovel_on_tbl = {
|
|
--on
|
|
[255]=use_misc_text,
|
|
[257]=use_misc_text,
|
|
[258]={[257]=use_shovel_on_pile_to_hole},
|
|
[268]={
|
|
[233]=use_shovel_to_unload_container, --use OBJ_SHOVEL on OBJ_MARTIAN_WHEEL_BARROW to OBJ_FURNACE
|
|
[257]=use_shovel_to_unload_container, --use OBJ_SHOVEL on OBJ_MARTIAN_WHEEL_BARROW to OBJ_HOLE
|
|
[268]=use_shovel_to_unload_container, --use OBJ_SHOVEL on OBJ_MARTIAN_WHEEL_BARROW to OBJ_MARTIAN_WHEEL_BARROW
|
|
[410]=use_shovel_to_unload_container, --use OBJ_SHOVEL on OBJ_MARTIAN_WHEEL_BARROW to OBJ_RAIL_CAR
|
|
},
|
|
[410]={
|
|
[233]=use_shovel_to_unload_container, --use OBJ_SHOVEL on OBJ_RAIL_CAR to OBJ_FURNACE
|
|
[257]=use_shovel_to_unload_container, --use OBJ_SHOVEL on OBJ_RAIL_CAR to OBJ_HOLE
|
|
[268]=use_shovel_to_unload_container, --use OBJ_SHOVEL on OBJ_RAIL_CAR to OBJ_MARTIAN_WHEEL_BARROW
|
|
[410]=use_shovel_to_unload_container, --use OBJ_SHOVEL on OBJ_RAIL_CAR to OBJ_RAIL_CAR
|
|
},
|
|
[442]={
|
|
[268]=use_shovel_on_ore_to_container, --use OBJ_SHOVEL on OBJ_PILE_OF_ROCKS to OBJ_MARTIAN_WHEEL_BARROW
|
|
[410]=use_shovel_on_ore_to_container}, --use OBJ_SHOVEL on OBJ_PILE_OF_ROCKS to OBJ_RAIL_CAR
|
|
[443]={
|
|
[268]=use_shovel_on_ore_to_container, --use OBJ_SHOVEL on OBJ_PILE_OF_IRON_ORE to OBJ_MARTIAN_WHEEL_BARROW
|
|
[410]=use_shovel_on_ore_to_container}, --use OBJ_SHOVEL on OBJ_PILE_OF_IRON_ORE to OBJ_RAIL_CAR
|
|
[444]={
|
|
[268]=use_shovel_on_ore_to_container, --use OBJ_SHOVEL on OBJ_PILE_OF_COAL to OBJ_MARTIAN_WHEEL_BARROW
|
|
[410]=use_shovel_on_ore_to_container}, --use OBJ_SHOVEL on OBJ_PILE_OF_COAL to OBJ_RAIL_CAR
|
|
[0]=use_tool_on_ground, --hole in ice, hole
|
|
}
|
|
|
|
function use_oil_on_door(obj, target_obj, actor)
|
|
if obj.obj_n == 235 and obj.frame_n ~= 4 then
|
|
printl("IT_HAS_NO_EFFECT")
|
|
return
|
|
end
|
|
|
|
if target_obj ~= nil then
|
|
if bit32.band(target_obj.quality, 0x80) == 0 then
|
|
printl("THIS_DOOR_IS_NOT_RUSTED")
|
|
else
|
|
target_obj.quality = bit32.band(target_obj.quality, 0x7f) --unset bit 7
|
|
printl("THE_DOOR_IS_UNSTUCK")
|
|
play_md_sfx(4)
|
|
if obj.stackable then
|
|
if obj.qty == 1 then
|
|
Obj.removeFromEngine(obj)
|
|
else
|
|
obj.qty = obj.qty - 1
|
|
end
|
|
else
|
|
Obj.removeFromEngine(obj)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function use_oil_on_dream_door(obj, target_obj, actor, target_x, target_y, target_z)
|
|
if map_get_tile_num(target_x, target_y, target_z) == 8 then
|
|
local melies = Actor.get(0x51)
|
|
Actor.set_talk_flag(melies, 6)
|
|
Actor.talk(melies)
|
|
finish_dream_quest(melies)
|
|
wake_from_dream()
|
|
else
|
|
printl("IT_HAS_NO_EFFECT")
|
|
end
|
|
end
|
|
|
|
function use_hand_mirror(obj, actor)
|
|
if actor.x >= 0x76 and actor.x <= 0x78 and actor.y >= 0xca and actor.y <= 0xcc and actor.z == 2 then
|
|
local lowell = Actor.get(0x50)
|
|
|
|
Actor.set_talk_flag(lowell, 6)
|
|
Actor.talk(lowell)
|
|
finish_dream_quest(lowell)
|
|
wake_from_dream()
|
|
else
|
|
printl("YOU_SEE_YOURSELF")
|
|
end
|
|
|
|
end
|
|
|
|
function use_radium(obj, target_obj, actor)
|
|
actor_radiation_check(actor, obj)
|
|
if obj.obj_n == 448 then --OBJ_BLOCK_OF_RADIUM
|
|
if target_obj.obj_n == 448 and target_obj.on_map then
|
|
local power_unit = map_get_obj(obj.x, obj.y, obj.z, 290) --OBJ_POWER_UNIT
|
|
if power_unit ~= nil then
|
|
target_obj = power_unit
|
|
end
|
|
end
|
|
|
|
if target_obj.obj_n == 290 then --OBJ_POWER_UNIT
|
|
if target_obj.frame_n == 1 then
|
|
printl("RADIUM_HAS_ALREADY_BEEN_INSTALLED")
|
|
else
|
|
Obj.removeFromEngine(obj)
|
|
play_md_sfx(4)
|
|
printl("THE_RADIUM_HAS_BEEN_INSTALLED")
|
|
target_obj.frame_n = 1
|
|
Actor.set_talk_flag(0x74, 2)
|
|
if Actor.get_talk_flag(0x74, 0) then
|
|
Actor.set_talk_flag(0x60, 2)
|
|
end
|
|
end
|
|
|
|
else
|
|
printl("IT_HAS_NO_EFFECT")
|
|
end
|
|
|
|
elseif obj.obj_n == 449 then --OBJ_CHIP_OF_RADIUM
|
|
if target_obj.qty < 0xf0 then
|
|
local qty = input_select_obj_qty(obj)
|
|
if qty == 0 then
|
|
return
|
|
end
|
|
|
|
if target_obj.qty + qty * 30 > 0xf0 then
|
|
qty = math.ceil((0xf0 - target_obj.qty) / 30)
|
|
printfl("THE_OBJ_ONLY_NEEDED_N_RADIUM_BLOCKS", target_obj.name, qty)
|
|
printfl("THE_OBJ_IS_FULLY_CHARGED", target_obj.name)
|
|
target_obj.qty = 0xf0
|
|
else
|
|
target_obj.qty = target_obj.qty + qty * 30
|
|
end
|
|
|
|
|
|
if obj.qty == qty then
|
|
Obj.removeFromEngine(obj)
|
|
else
|
|
obj.qty = obj.qty - qty
|
|
end
|
|
else
|
|
printfl("THE_OBJ_IS_FULLY_CHARGED", target_obj.name)
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
function use_head_gear(obj, target_obj, actor)
|
|
local machine
|
|
if target_obj.obj_n == 289 then --OBJ_DREAM_MACHINE2
|
|
local machine = map_get_obj(target_obj.x, target_obj.y, target_obj.z, 288)
|
|
if machine == nil then
|
|
printl("IT_HAS_NO_EFFECT")
|
|
return
|
|
end
|
|
else
|
|
machine = target_obj
|
|
end
|
|
|
|
local loc = machine.xyz
|
|
|
|
machine = Obj.new(100)
|
|
machine.frame_n = 1
|
|
Obj.moveToMap(machine, loc)
|
|
|
|
printl("THE_HEADGEAR_IS_INSTALLED")
|
|
|
|
Actor.set_talk_flag(0x74, 4)
|
|
if Actor.get_talk_flag(0x74, 0) then
|
|
Actor.set_talk_flag(0x60, 2)
|
|
end
|
|
|
|
end
|
|
|
|
function use_dream_machine(panel_obj)
|
|
if Actor.get_talk_flag(0x46, 3) then
|
|
printl("THE_DREAM_MACHINES_SEEM_TO_HAVE_CEASED_FUNCTIONING")
|
|
return
|
|
end
|
|
|
|
local z = panel_obj.z
|
|
local power_unit
|
|
local dream_quality
|
|
local headgear_installed = false
|
|
local seat_x, seat_y
|
|
for obj in find_obj_from_area(panel_obj.x - 5, panel_obj.y - 5, z, 11, 11) do
|
|
local obj_n = obj.obj_n
|
|
if obj_n == 290 and obj.frame_n == 1 then --OBJ_POWER_UNIT
|
|
power_unit = obj
|
|
elseif obj_n == 100 then --OBJ_DREAM_MACHINE
|
|
headgear_installed = true
|
|
elseif obj_n == 289 then --OBJ_DREAM_MACHINE2
|
|
seat_x = obj.x
|
|
seat_y = obj.y
|
|
elseif obj_n == 288 then --OBJ_DREAM_MACHINE2
|
|
dream_quality = obj.quality
|
|
end
|
|
end
|
|
|
|
local actor_in_seat = map_get_actor(seat_x, seat_y, z)
|
|
|
|
if power_unit == nil or dream_quality == nil or not headgear_installed then
|
|
printl("THE_MACHINE_DOES_NOT_WORK")
|
|
return
|
|
end
|
|
|
|
local martian_obj = map_get_obj(seat_x, seat_y, z, 291) --OBJ_UNCONSCIOUS_MARTIAN
|
|
if martian_obj ~= nil then
|
|
if Actor.get_talk_flag(0x21, 2) or not Actor.get_talk_flag(0x61, 4) then
|
|
printl("IT_HAS_NO_EFFECT")
|
|
else
|
|
play_midgame_sequence(5)
|
|
local martian = Actor.get(0x21)
|
|
Actor.talk(martian)
|
|
Actor.set_talk_flag(martian, 2)
|
|
martian.x = seat_x
|
|
martian.y = seat_y + 1
|
|
martian.z = panel_obj.z
|
|
kill_actor(martian)
|
|
Obj.removeFromEngine(martian_obj)
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
local metal_woman_obj = map_get_obj(seat_x, seat_y, z, 287) --OBJ_METAL_WOMAN
|
|
if metal_woman_obj ~= nil then
|
|
if metal_woman_obj.quality == 0 then
|
|
printl("IT_HAS_NO_EFFECT")
|
|
else
|
|
--FIXME implement metal woman activation logic
|
|
end
|
|
elseif actor_in_seat ~= nil then
|
|
if z ~= 0 then
|
|
wake_from_dream()
|
|
else
|
|
if dream_quality < 2 then
|
|
Actor.set_talk_flag(0x60, 3)
|
|
end
|
|
if dream_quality == 3 then
|
|
if Actor.get_talk_flag(0x46, 0) then
|
|
--FIXME call sub_3F624
|
|
else
|
|
printl("THE_MACHINE_DOES_NOT_WORK")
|
|
end
|
|
else
|
|
actor_use_dream_machine(actor_in_seat, dream_quality)
|
|
end
|
|
|
|
end
|
|
else
|
|
printl("THERE_IS_NOBODY_SITTING_IN_THE_MACHINE")
|
|
end
|
|
|
|
end
|
|
|
|
function use_sprayer_system(panel_obj)
|
|
end
|
|
|
|
function use_lens_controls(panel_obj)
|
|
end
|
|
|
|
function use_pump_controls(panel_obj)
|
|
end
|
|
|
|
local use_panel_tbl = {
|
|
[0]=function() printl("YOU_ARE_COMPLETELY_UNSURE_WHAT_YOU_JUST_DID") end,
|
|
[1]=function() printl("YOU_ACTUATE_THE_MECHANISM_TO_NO_APPARENT_EFFECT") end,
|
|
[2]=function() printl("STATUS_LIGHTS_CHANGE_BUT_YOU_SEE_NO_OTHER_EFFECT") end,
|
|
[3]=function() printl("LIGHTS_FLASH_AND_CHANGE_COLOR_BUT_NOTHING_ELSE_HAPPENS") end,
|
|
[4]=use_dream_machine,
|
|
[5]=use_sprayer_system,
|
|
[6]=use_lens_controls,
|
|
[7]=use_pump_controls,
|
|
}
|
|
|
|
function use_panel(obj, actor)
|
|
if bit32.band(obj.quality, 2) ~= 0 then
|
|
printl("THE_PANEL_IS_BROKEN")
|
|
return
|
|
end
|
|
if bit32.band(obj.quality, 1) ~= 0 then
|
|
printl("THE_PANEL_IS_NOT_INSTALLED")
|
|
return
|
|
end
|
|
|
|
local cabinet = map_get_obj(obj.x, obj.y, obj.z, 457) --OBJ_CABINET
|
|
if cabinet == nil then
|
|
printl("PANELS_ARE_ONLY_INSTALLED_ONTO_CABINETS")
|
|
return
|
|
end
|
|
|
|
local quality = cabinet.quality
|
|
if use_panel_tbl[quality] ~= nil then
|
|
use_panel_tbl[quality](obj)
|
|
else
|
|
printl("IT_HAS_NO_EFFECT")
|
|
end
|
|
end
|
|
|
|
function has_minotaur_left_the_shop(cur_z)
|
|
for i=1,0xff do
|
|
local actor = Actor.get(i)
|
|
if actor.obj_n == 398 then --OBJ_MINOTAUR
|
|
if actor.z == cur_z and not Actor.get_talk_flag(0x54, 6)
|
|
and actor.x >= 0x37 and actor.y <= 0x37 then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
function use_switch(obj, actor)
|
|
local switch_qty = obj.qty
|
|
local switch_quality = obj.quality
|
|
local target_obj
|
|
|
|
local num_switches = 0
|
|
local switches = {}
|
|
|
|
for obj in find_obj_from_area(obj.x - 32, obj.y - 32, obj.z, 64, 64) do
|
|
if obj.obj_n == 179 or obj.obj_n == 227 then --OBJ_CLOSED_DOOR, OBJ_DOOR3
|
|
if bit32.band(obj.quality, 0x7f) == switch_qty then
|
|
target_obj = obj
|
|
end
|
|
elseif (obj.obj_n == 311 or obj.obj_n == 312 or obj.obj_n == 196) then --and obj.quality < 2 then
|
|
if num_switches < 4 then
|
|
num_switches = num_switches + 1
|
|
switches[num_switches] = obj
|
|
end
|
|
end
|
|
end
|
|
|
|
if target_obj == nil then
|
|
printl("STRANGELY_NOTHING_HAPPENS")
|
|
return
|
|
end
|
|
|
|
if num_switches == 0 then
|
|
printl("STRANGELY_IT_DOESNT_MOVE")
|
|
return
|
|
end
|
|
|
|
local frame_n = 0
|
|
if switch_quality == 1 then
|
|
if bit32.band(target_obj.quality, 0x80) == 0 then
|
|
target_obj.quality = bit32.bor(target_obj.quality, 0x80)
|
|
else
|
|
target_obj.quality = bit32.band(target_obj.quality, 0x7f)
|
|
frame_n = 1
|
|
end
|
|
else
|
|
local old_frame_n = target_obj.frame_n
|
|
target_obj.frame_n = bit32.band(old_frame_n, 2) + 5
|
|
play_door_sfx()
|
|
if old_frame_n < 4 then
|
|
target_obj.frame_n = bit32.band(old_frame_n, 2) + 9
|
|
frame_n = 1
|
|
else
|
|
target_obj.frame_n = bit32.band(old_frame_n, 2) + 1
|
|
|
|
if g_in_dream_mode and g_current_dream_stage == 0x44 and has_minotaur_left_the_shop(target_obj.z) then
|
|
complete_tiffany_stage()
|
|
return
|
|
end
|
|
end
|
|
play_door_sfx()
|
|
end
|
|
|
|
for i=1,num_switches do
|
|
switches[i].frame_n = frame_n
|
|
end
|
|
play_md_sfx(0x11)
|
|
end
|
|
|
|
function use_drawbridge_lever(obj, actor)
|
|
--FIXME
|
|
end
|
|
|
|
function use_cheat_lever(obj, actor)
|
|
--FIXME
|
|
end
|
|
|
|
function use_cheat_lever2(obj, actor)
|
|
--FIXME
|
|
end
|
|
|
|
local switch_qual_tbl = {
|
|
[1] = use_switch,
|
|
[2] = use_switch,
|
|
[10] = use_drawbridge_lever,
|
|
[20] = use_cheat_lever,
|
|
[21] = use_cheat_lever2,
|
|
}
|
|
|
|
function use_switch_device(obj, actor)
|
|
if switch_qual_tbl[obj.quality] ~= nil then
|
|
switch_qual_tbl[obj.quality](obj, actor)
|
|
else
|
|
printl("WHAT_AN_ODD_LEVER")
|
|
end
|
|
end
|
|
|
|
function use_dreamstuff(obj, actor)
|
|
printl("YOU_IMAGINE")
|
|
|
|
for item in container_objs(obj) do
|
|
if item.obj_n < 342 then -- OBJ_POOR_MONK
|
|
--object
|
|
print(item.look_string.."\n")
|
|
if obj.on_map then
|
|
Obj.moveToMap(item, obj.xyz)
|
|
else
|
|
local parent = obj.parent
|
|
if parent.luatype == "actor" then
|
|
Obj.moveToInv(item, parent.actor_num)
|
|
else
|
|
Obj.moveToCont(item, parent)
|
|
end
|
|
end
|
|
else
|
|
--actor
|
|
print(item.name.."\n")
|
|
local spawned_actor = Actor.new(item.obj_n, actor.x, actor.y, actor.z)
|
|
|
|
actor_init(spawned_actor, obj.quality + 1) -- alignment
|
|
toss_actor(spawned_actor, actor.x, actor.y, actor.z)
|
|
spawned_actor.wt = item.quality
|
|
end
|
|
Obj.removeFromEngine(obj)
|
|
return
|
|
end
|
|
|
|
printl("NOTHING")
|
|
end
|
|
|
|
function use_obj_on_spray_gun(obj, target_obj, actor)
|
|
if obj.obj_n == 119 and target_obj.quality == 0 then --OBJ_BOTTLE_OF_GREEN_PAINT
|
|
target_obj.quality = 1
|
|
target_obj.qty = 20
|
|
printl("SPRAY_GUN_GREEN_PAINT")
|
|
elseif obj.obj_n == 128 and target_obj.quality ~= 0 then --OBJ_WEED_KILLER
|
|
target_obj.quality = 0
|
|
target_obj.qty = 10
|
|
printl("SPRAY_GUN_WEED_KILLER")
|
|
else
|
|
local spray_gun_qty = target_obj.qty + 10
|
|
if spray_gun_qty > 0x1e then
|
|
spray_gun_qty = 0x1e
|
|
end
|
|
target_obj.qty = spray_gun_qty
|
|
printl("SPRAY_GUN_10_MORE_CHARGES")
|
|
end
|
|
|
|
Obj.removeFromEngine(obj)
|
|
end
|
|
|
|
function use_spray_gun(obj, target_obj, actor)
|
|
if obj.qty == 0 then
|
|
printl("THERE_IS_NOTHING_IN_THE_GUN")
|
|
return
|
|
end
|
|
|
|
if obj.quality ~= 0 then
|
|
obj.qty = obj.qty - 1
|
|
if target_obj.luatype == "actor" and target_obj.obj_n == 145 then --OBJ_MONSTER_FOOTPRINTS
|
|
target_obj.obj_n = 364 --OBJ_PROTO_MARTIAN
|
|
printfl("BECOMES_VISIBLE", target_obj.name)
|
|
else
|
|
if target_obj.luatype == "actor" and not target_obj.visible then
|
|
target_obj.visible = true
|
|
printfl("BECOMES_VISIBLE", target_obj.name)
|
|
elseif target_obj.luatype == "obj" and target_obj.invisible then
|
|
target_obj.invisible = false
|
|
printfl("BECOMES_VISIBLE", target_obj.name)
|
|
else
|
|
printl("IT_HAS_NO_EFFECT")
|
|
end
|
|
end
|
|
elseif target_obj.luatype == "actor" then
|
|
attack_target_with_weapon(actor, target_obj.x, target_obj.y, obj)
|
|
elseif is_plant_obj(target_obj) then
|
|
hit_target(target_obj, RED_HIT_TILE)
|
|
printl("YOU_KILLED_THE_PLANT")
|
|
if target_obj.obj_n == 205 then --OBJ_VINE
|
|
Actor.set_talk_flag(0x30, 7)
|
|
Obj.removeFromEngine(target_obj)
|
|
elseif target_obj.obj_n == 408 then --OBJ_TREE
|
|
target_obj.obj_n = 166 --OBJ_DEAD_TREE
|
|
else
|
|
Obj.removeFromEngine(target_obj)
|
|
end
|
|
else
|
|
obj.qty = obj.qty - 1
|
|
printl("IT_HAS_NO_EFFECT")
|
|
end
|
|
end
|
|
|
|
local usecode_table = {
|
|
--OBJ_RUBY_SLIPPERS
|
|
[12]=use_ruby_slippers,
|
|
--OBJ_RUBBER_GLOVES
|
|
[38]=use_ready_obj,
|
|
--OBJ_SLEDGE_HAMMER
|
|
[52]={
|
|
--on
|
|
[404]={ --OBJ_REPLACEMENT_TRACK
|
|
--to
|
|
[405]=use_sledge_hammer_on_replacement_track_to_broken_track
|
|
}
|
|
},
|
|
--OBJ_PLIERS
|
|
[53]={
|
|
--on
|
|
[199]={--OBJ_CABLE_SPOOL
|
|
--to
|
|
[201]=use_pliers_on_spool_to_tower, --OBJ_TOWER_TOP
|
|
[215]=use_pliers_on_spool_to_tower, --OBJ_POWER_CABLE1
|
|
}
|
|
},
|
|
--OBJ_PICK
|
|
[65]={[255]=use_misc_text,[257]=use_misc_text}, --hole in ice, hole
|
|
--OBJ_SHOVEL
|
|
[66]=use_shovel_on_tbl,
|
|
--OBJ_HOE
|
|
[67]={[255]=use_misc_text,[257]=use_misc_text}, --hole in ice, hole
|
|
--OBJ_BERRY
|
|
[73]=use_berry,
|
|
--OBJ_BERRY1
|
|
[74]=use_berry,
|
|
--OBJ_BERRY2
|
|
[75]=use_berry,
|
|
--OBJ_BERRY3
|
|
[76]=use_berry,
|
|
--OBJ_BERRY4
|
|
[77]=use_red_berry,
|
|
--OBJ_CLUMP_OF_ROUGE_BERRIES
|
|
[78]=use_misc_text,
|
|
[86]=use_container,
|
|
[87]=use_container,
|
|
--OBJ_MANUSCRIPT
|
|
[88]={
|
|
--on
|
|
[84]=use_manuscript_on_mailbox, --OBJ_MAILBOX
|
|
},
|
|
[96]=use_sextant,
|
|
[102]={[86]=use_crate,[427]=use_prybar_on_hatch},
|
|
[104]=use_container,
|
|
--OBJ_FOLDED_TENT
|
|
[106]=use_tent,
|
|
--OBJ_BOTTLE_OF_GREEN_PAINT
|
|
[119]={
|
|
--on
|
|
--OBJ_WEED_SPRAYER
|
|
[129]=use_obj_on_spray_gun,
|
|
--OBJ_SPRAY_GUN
|
|
[261]=use_obj_on_spray_gun,
|
|
},
|
|
--OBJ_CAN_OF_LAMP_OIL
|
|
[124]={
|
|
--on
|
|
--OBJ_CLOSED_DOOR
|
|
[179]=use_oil_on_door,
|
|
--OBJ_DOOR3
|
|
[227]=use_oil_on_door,
|
|
--OBJ_CLOSED_HATCH
|
|
[421]=use_oil_on_door,
|
|
--OBJ_DOOR
|
|
[152]=use_oil_on_door,
|
|
--OBJ_DOOR1
|
|
[219]=use_oil_on_door,
|
|
--OBJ_DOOR2
|
|
[222]=use_oil_on_door,
|
|
[0]=use_oil_on_dream_door,
|
|
},
|
|
--OBJ_WEED_KILLER
|
|
[128]={
|
|
--on
|
|
--OBJ_WEED_SPRAYER
|
|
[129]=use_obj_on_spray_gun,
|
|
--OBJ_SPRAY_GUN
|
|
[261]=use_obj_on_spray_gun,
|
|
},
|
|
--OBJ_WEED_SPRAYER
|
|
[129]={
|
|
--on
|
|
[0]=use_spray_gun
|
|
},
|
|
--OBJ_BLOB_OF_OXIUM
|
|
[131]=use_misc_text,
|
|
--OBJ_WRENCH
|
|
[135]={
|
|
--on
|
|
[411]=use_wrench_on_switchbar,
|
|
[440]=use_wrench_on_drill,
|
|
[458]=use_wrench_on_panel
|
|
},
|
|
--OBJ_TONGS
|
|
[136]=use_ready_obj,
|
|
--OBJ_REPAIRED_BELT
|
|
[144]={
|
|
--on
|
|
[192]=use_fixed_belt_on_bare_rollers,
|
|
},
|
|
--OBJ_HAND_MIRROR
|
|
[147]=use_hand_mirror,
|
|
--OBJ_BOOK
|
|
[148]=use_reading_material,
|
|
--OBJ_NOTE
|
|
[151]=use_reading_material,
|
|
--OBJ_DOOR
|
|
[152]=use_door,
|
|
[181]=use_gate,
|
|
--OBJ_CAMERA
|
|
[184]=use_misc_text,
|
|
--OBJ_LEVER
|
|
[196]=use_switch_device,
|
|
--OBJ_CABLE_SPOOL
|
|
[199]=use_misc_text,
|
|
[212]=use_oxium_bin,
|
|
[222]=use_door,
|
|
--OBJ_GONG_HAMMER
|
|
[231]={
|
|
--on
|
|
[130]=use_hammer_on_oxium_geode, --OBJ_OXIUM_GEODE
|
|
[298]=use_gong, --OBJ_GONG
|
|
--FIXME OBJ_BRASS_CHEST, OBJ_OBSIDIAN_BOX, OBJ_STEAMER_TRUNK, OBJ_OPEN_BRASS_TRUNK use_crate
|
|
},
|
|
--OBJ_POTASH (this is actually oil when frame_n == 4)
|
|
[235]={
|
|
--on
|
|
--OBJ_CLOSED_DOOR
|
|
[179]=use_oil_on_door,
|
|
--OBJ_DOOR3
|
|
[227]=use_oil_on_door,
|
|
--OBJ_CLOSED_HATCH
|
|
[421]=use_oil_on_door,
|
|
--OBJ_DOOR
|
|
[152]=use_oil_on_door,
|
|
--OBJ_DOOR1
|
|
[219]=use_oil_on_door,
|
|
--OBJ_DOOR2
|
|
[222]=use_oil_on_door,
|
|
[0]=use_oil_on_dream_door,
|
|
},
|
|
--OBJ_SCROLL
|
|
[243]=use_reading_material,
|
|
--OBJ_SPRAY_GUN
|
|
[261]={
|
|
--on
|
|
[0]=use_spray_gun
|
|
},
|
|
--OBJ_MARTIAN_HOE
|
|
[263]={[255]=use_misc_text,[257]=use_misc_text}, --hole in ice, hole
|
|
--OBJ_MARTIAN_SHOVEL
|
|
[267]=use_shovel_on_tbl,
|
|
[273]={[86]=use_crate}, --Hammer needs more codes
|
|
--OBJ_CYMBALS
|
|
[280]=use_musical_instrument,
|
|
--OBJ_TAMBORINE
|
|
[281]=use_musical_instrument,
|
|
--OBJ_DRUM
|
|
[282]=use_musical_instrument,
|
|
--OBJ_ACCORDION
|
|
[283]=use_musical_instrument,
|
|
[284]=use_container,
|
|
--OBJ_SPITTOON
|
|
[286]=use_spittoon,
|
|
--OBJ_DREAM_MACHINE1
|
|
[288]=use_misc_text,
|
|
--OBJ_MARTIAN_CLOCK
|
|
[293]=use_misc_text,
|
|
--OBJ_HEADGEAR
|
|
[296]={
|
|
--on
|
|
[288]=use_head_gear, --OBJ_DREAM_MACHINE1
|
|
[289]=use_head_gear, --OBJ_DREAM_MACHINE2
|
|
},
|
|
--OBJ_SWITCH
|
|
[311]=use_switch_device,
|
|
--OBJ_SWITCH1
|
|
[312]=use_switch_device,
|
|
--OBJ_OXYGENATED_AIR_MACHINE
|
|
[323]=use_misc_text,
|
|
--OBJ_MARTIAN_PICK
|
|
[327]={[255]=use_misc_text,[257]=use_misc_text}, --hole in ice, hole
|
|
[331]=use_dreamstuff,
|
|
[399]=use_pool_table,
|
|
--OBJ_POOL_QUE
|
|
[401]=use_ready_obj,
|
|
[411]=use_switch_bar,
|
|
--OBJ_CLOSED_HATCH
|
|
[421]=use_door,
|
|
--OBJ_HEART_STONE
|
|
[426]={
|
|
--on
|
|
[287]= use_heartstone_on_metal_woman, --OBJ_METAL_WOMAN
|
|
},
|
|
[427]=use_misc_text,
|
|
--OBJ_ASSEMBLED_DRILL
|
|
[441]=use_assembled_drill,
|
|
--OBJ_PILE_OF_ROCKS
|
|
[442]=use_misc_text,
|
|
--OBJ_PILE_OF_IRON_ORE
|
|
[443]=use_misc_text,
|
|
--OBJ_PILE_OF_COAL
|
|
[444]=use_misc_text,
|
|
--OBJ_BLOCK_OF_RADIUM
|
|
[448]={
|
|
--on
|
|
[290]=use_radium, --OBJ_POWER_UNIT
|
|
[448]=use_radium, --OBJ_BLOCK_OF_RADIUM
|
|
},
|
|
--OBJ_CHIP_OF_RADIUM
|
|
[449]={
|
|
--on
|
|
[240]=use_radium, --OBJ_HEAT_RAY_GUN
|
|
[241]=use_radium, --OBJ_FREEZE_RAY_GUN
|
|
},
|
|
--OBJ_PANEL
|
|
[458]=use_panel,
|
|
}
|
|
|
|
function ready_winged_shoes(obj, actor)
|
|
local player_loc = player_get_location()
|
|
if player_loc.z == 2 then
|
|
local bridge = Obj.new(146)
|
|
bridge.temporary = false
|
|
Obj.moveToMap(bridge, 0xc9, 0x9b, 2)
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function ready_tongs(obj, actor)
|
|
printl("THE_TONGS_WILL_NOW_PROTECT_YOUR_HANDS")
|
|
return true
|
|
end
|
|
|
|
function ready_throw_rug(obj, actor)
|
|
obj.obj_n = 162 --Change to red cape
|
|
return true
|
|
end
|
|
|
|
local usecode_ready_obj_table = {
|
|
[15]=ready_winged_shoes,
|
|
[136]=ready_tongs,
|
|
[161]=ready_throw_rug,
|
|
}
|
|
|
|
function unready_winged_shoes(obj, actor)
|
|
printl("THEY_WONT_COME_OFF")
|
|
return false
|
|
end
|
|
|
|
local usecode_unready_obj_table = {
|
|
[15]=unready_winged_shoes,
|
|
}
|
|
|
|
function move_drill(obj, rel_x, rel_y)
|
|
if rel_x ~= 0 and rel_y ~= 0 then
|
|
return false
|
|
end
|
|
|
|
if rel_x < 0 then
|
|
obj.frame_n = 1
|
|
elseif rel_x > 0 then
|
|
obj.frame_n = 4
|
|
elseif rel_y < 0 then
|
|
obj.frame_n = 3
|
|
elseif rel_y > 0 then
|
|
obj.frame_n = 5
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function move_wheelbarrow(obj, rel_x, rel_y)
|
|
if rel_x ~= 0 and rel_y ~= 0 then
|
|
return false
|
|
end
|
|
|
|
if rel_x < 0 then
|
|
obj.frame_n = 3
|
|
elseif rel_x > 0 then
|
|
obj.frame_n = 1
|
|
elseif rel_y < 0 then
|
|
obj.frame_n = 0
|
|
elseif rel_y > 0 then
|
|
obj.frame_n = 2
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function move_rail_cart(obj, rel_x, rel_y)
|
|
local frame_n = obj.frame_n
|
|
if rel_x ~= 0 and rel_y ~= 0 then
|
|
printl("IT_WONT_GO_IN_THAT_DIRECTION")
|
|
return false
|
|
end
|
|
if (rel_x < 0 or rel_x > 0) and (frame_n == 1 or frame_n == 3 or frame_n == 5) then
|
|
printl("IT_WONT_GO_IN_THAT_DIRECTION")
|
|
return false
|
|
end
|
|
if (rel_y < 0 or rel_y > 0) and (frame_n == 0 or frame_n == 2 or frame_n == 4) then
|
|
printl("IT_WONT_GO_IN_THAT_DIRECTION")
|
|
return false
|
|
end
|
|
if check_for_track(obj, rel_x, rel_y) == false then
|
|
printl("IT_WONT_GO_IN_THAT_DIRECTION")
|
|
return false
|
|
end
|
|
|
|
move_car_obj(obj, rel_x, rel_y)
|
|
return false
|
|
end
|
|
|
|
function check_for_track(car, rel_x, rel_y)
|
|
local x = car.x + rel_x
|
|
local y = car.y + rel_y
|
|
|
|
for obj in objs_at_loc(x, y, car.z) do
|
|
if (obj.obj_n >= 412 and obj.obj_n <= 414) or obj.obj_n == 419 or obj.obj_n == 175 or obj.obj_n == 163 then --track object
|
|
|
|
local track_frame_n = obj.frame_n
|
|
if (car.frame_n % 2) == track_frame_n or track_frame_n == 2 or obj.obj_n == 412 or obj.obj_n == 175 or obj.obj_n == 163 then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
elseif is_blood(obj.obj_n) == false and obj.obj_n ~= 417 then --MARTIAN_BARGE
|
|
return false
|
|
end
|
|
end
|
|
|
|
if map_get_obj(x, y, car.z, 175, true) then
|
|
return true
|
|
end
|
|
|
|
if map_get_obj(x, y, car.z, 412, true) then
|
|
return true
|
|
end
|
|
|
|
local tile_num = map_get_tile_num(x,y, car.z)
|
|
if is_track_tile(tile_num) then
|
|
return true
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function move_car_obj(obj, rel_x, rel_y)
|
|
obj.x = obj.x + rel_x
|
|
obj.y = obj.y + rel_y
|
|
return true
|
|
end
|
|
|
|
function move_plank(obj, rel_x, rel_y)
|
|
obj.x = obj.x + rel_x
|
|
obj.y = obj.y + rel_y
|
|
return true
|
|
end
|
|
|
|
function is_track_tile(tile_num)
|
|
if tile_num == 108 or tile_num == 109 or tile_num == 110 or tile_num == 77 or tile_num == 79 then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
local usecode_move_obj_table = {
|
|
[268]=move_wheelbarrow,
|
|
[395]=move_plank,
|
|
[410]=move_rail_cart,
|
|
[441]=move_drill,
|
|
}
|
|
|
|
function has_usecode(obj, usecode_type)
|
|
--print("has_usecode("..obj.obj_n..", "..usecode_type..")\n")
|
|
if usecode_type == USE_EVENT_USE and usecode_table[obj.obj_n] ~= nil then
|
|
return true
|
|
elseif usecode_type == USE_EVENT_READY and (usecode_ready_obj_table[obj.obj_n] ~= nil or usecode_unready_obj_table[obj.obj_n] ~= nil)then
|
|
return true
|
|
elseif usecode_type == USE_EVENT_MOVE and usecode_move_obj_table[obj.obj_n] ~= nil then
|
|
return true
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function use_obj_on_to(obj, target_obj, actor, use_to_tbl)
|
|
local dir = get_direction(i18n("TO"))
|
|
if dir == nil then
|
|
printl("NOTHING")
|
|
return
|
|
end
|
|
|
|
local to_x, to_y = direction_get_loc(dir, actor.x, actor.y)
|
|
|
|
local to_obj = map_get_obj(to_x, to_y, actor.z)
|
|
|
|
if to_obj ~= nil then
|
|
print(to_obj.name.."\n\n")
|
|
local func = use_to_tbl[to_obj.obj_n]
|
|
if func ~= nil then
|
|
func(obj, target_obj, to_obj, actor)
|
|
end
|
|
else
|
|
printl("SOMETHING")
|
|
end
|
|
end
|
|
|
|
function use_obj_on(obj, actor, use_on_tbl)
|
|
local dir = get_direction(i18n("ON"))
|
|
if dir == nil then
|
|
printl("NOTHING")
|
|
return
|
|
end
|
|
|
|
local target_x, target_y = direction_get_loc(dir, actor.x, actor.y)
|
|
|
|
local target_entity = map_get_actor(target_x, target_y, actor.z)
|
|
if target_entity == nil then
|
|
target_entity = map_get_obj(target_x, target_y, actor.z)
|
|
end
|
|
|
|
if target_entity ~= nil then
|
|
print(target_entity.name.."\n\n")
|
|
local on = use_on_tbl[target_entity.obj_n]
|
|
if on ~= nil then
|
|
if type(on) == "function" then
|
|
local func = on
|
|
func(obj, target_entity, actor)
|
|
else
|
|
use_obj_on_to(obj, target_entity, actor, on)
|
|
end
|
|
else
|
|
local func = use_on_tbl[0]
|
|
if func ~= nil then
|
|
func(obj, target_entity, actor)
|
|
else
|
|
printl("NO_EFFECT")
|
|
end
|
|
end
|
|
else
|
|
local func = use_on_tbl[0]
|
|
if func ~= nil then
|
|
func(obj, nil, actor, target_x, target_y, actor.z)
|
|
else
|
|
printl("NOTHING")
|
|
end
|
|
end
|
|
end
|
|
|
|
function can_interact_with_obj(actor, obj)
|
|
if obj.on_map then
|
|
--FIXME get_combat_range()
|
|
local distance = actor_find_max_wrapped_xy_distance(actor, obj.x, obj.y)
|
|
if actor_is_affected_by_purple_berries(actor.actor_num) and distance <= actor.level then
|
|
return true
|
|
end
|
|
|
|
if distance > 1 then
|
|
printl("OUT_OF_RANGE")
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function use_obj(obj, actor)
|
|
if not can_interact_with_obj(actor, obj) then
|
|
return
|
|
end
|
|
|
|
if type(usecode_table[obj.obj_n]) == "function" then
|
|
local func = usecode_table[obj.obj_n]
|
|
if func ~= nil then
|
|
print("\n")
|
|
func(obj, actor)
|
|
end
|
|
else
|
|
use_obj_on(obj, actor, usecode_table[obj.obj_n])
|
|
end
|
|
|
|
update_objects_around_party()
|
|
end
|
|
|
|
function ready_obj(obj, actor)
|
|
if type(usecode_ready_obj_table[obj.obj_n]) == "function" and obj.readied == false then
|
|
local func = usecode_ready_obj_table[obj.obj_n]
|
|
if func ~= nil then
|
|
print("\n")
|
|
return func(obj, actor)
|
|
end
|
|
end
|
|
|
|
if type(usecode_unready_obj_table[obj.obj_n]) == "function" and obj.readied == true then
|
|
local func = usecode_unready_obj_table[obj.obj_n]
|
|
if func ~= nil then
|
|
print("\n")
|
|
return func(obj, actor)
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function move_obj(obj, rel_x, rel_y)
|
|
if usecode_move_obj_table[obj.obj_n] ~= nil then
|
|
return usecode_move_obj_table[obj.obj_n](obj, rel_x, rel_y)
|
|
end
|
|
return true
|
|
end
|
|
|
|
function is_ranged_select(operation)
|
|
return actor_is_affected_by_purple_berries(Actor.get_player_actor().actor_num)
|
|
end
|