mirror of
https://github.com/lcdr/luserver.git
synced 2025-12-19 20:49:51 -06:00
v2017.11.26
- fixed spider cinematic being played for everyone connected - fixed rocco sirocco's cinematic not being played - implemented teleports between NS, starbase and lego club station
This commit is contained in:
@@ -16,17 +16,6 @@ class AddMission(ChatCommand):
|
||||
else:
|
||||
sender.char.add_mission(int(args.mission))
|
||||
|
||||
class AutocompleteMissions(ChatCommand):
|
||||
def __init__(self):
|
||||
super().__init__("autocompletemissions")
|
||||
self.command.add_argument("--enable", type=toggle_bool)
|
||||
|
||||
def run(self, args, sender):
|
||||
if args.enable is None:
|
||||
sender.char.autocomplete_missions = not sender.char.autocomplete_missions
|
||||
else:
|
||||
sender.char.autocomplete_missions = args.enable
|
||||
|
||||
class CompleteMission(ChatCommand):
|
||||
def __init__(self):
|
||||
super().__init__("completemission")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import asyncio
|
||||
import datetime
|
||||
import logging
|
||||
import math
|
||||
import os
|
||||
import re
|
||||
import secrets
|
||||
@@ -8,8 +9,12 @@ import time
|
||||
|
||||
from ..auth import Account, GMLevel, PasswordState
|
||||
from ..bitstream import BitStream, c_bool, c_ushort
|
||||
from ..ldf import LDF, LDFDataType
|
||||
from ..messages import WorldClientMsg
|
||||
from ..world import server
|
||||
from ..components.physics import AABB, CollisionSphere, PrimitiveModelType
|
||||
from ..math.quaternion import Quaternion
|
||||
from ..math.vector import Vector3
|
||||
from .command import ChatCommand, normal_bool
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -112,6 +117,45 @@ class Mute(ChatCommand):
|
||||
else:
|
||||
server.chat.sys_msg_sender("Player not connected")
|
||||
|
||||
class PhysicsDebug(ChatCommand):
|
||||
def __init__(self):
|
||||
super().__init__("physicsdebug")
|
||||
self.debug_markers = []
|
||||
server.add_handler("proximity_radius", self.on_proximity_radius)
|
||||
|
||||
def run(self, args, sender):
|
||||
if self.debug_markers:
|
||||
for marker in self.debug_markers:
|
||||
server.replica_manager.destruct(marker)
|
||||
self.debug_markers.clear()
|
||||
else:
|
||||
for obj in server.general.tracked_objects.copy():
|
||||
self.spawn_debug_marker(obj)
|
||||
|
||||
def on_proximity_radius(self, obj):
|
||||
if not self.debug_markers:
|
||||
return
|
||||
self.spawn_debug_marker(obj)
|
||||
|
||||
def spawn_debug_marker(self, obj):
|
||||
coll = server.general.tracked_objects[obj]
|
||||
set_vars = {"parent": obj, "rotation": Quaternion.identity}
|
||||
if isinstance(coll, AABB):
|
||||
config = LDF()
|
||||
config.ldf_set("primitiveModelType", LDFDataType.INT32, PrimitiveModelType.Cuboid)
|
||||
config.ldf_set("primitiveModelValueX", LDFDataType.FLOAT, coll.max.x-coll.min.x)
|
||||
config.ldf_set("primitiveModelValueY", LDFDataType.FLOAT, coll.max.y-coll.min.y)
|
||||
config.ldf_set("primitiveModelValueZ", LDFDataType.FLOAT, coll.max.z-coll.min.z)
|
||||
|
||||
set_vars["position"] = Vector3((coll.min.x+coll.max.x)/2, coll.min.y, (coll.min.z+coll.max.z)/2)
|
||||
set_vars["config"] = config
|
||||
marker = server.spawn_object(14510, set_vars)
|
||||
elif isinstance(coll, CollisionSphere):
|
||||
set_vars["position"] = coll.position
|
||||
set_vars["scale"] = math.sqrt(coll.sq_radius)/5
|
||||
marker = server.spawn_object(6548, set_vars)
|
||||
self.debug_markers.append(marker)
|
||||
|
||||
class ResetPassword(ChatCommand):
|
||||
def __init__(self):
|
||||
super().__init__("resetpassword")
|
||||
|
||||
@@ -561,6 +561,10 @@ class CharacterComponent(Component, CharActivity, CharCamera, CharMission, CharP
|
||||
def bounce_notification(self, object_id_bounced:c_int64=None, object_id_bouncer:c_int64=None, success:bool=None):
|
||||
pass
|
||||
|
||||
@single
|
||||
def display_zone_summary(self, is_property_map:bool=False, is_zone_start:bool=False, sender:GameObject=None):
|
||||
pass
|
||||
|
||||
@broadcast
|
||||
def start_arranging_with_item(self, first_time:bool=True, build_area:GameObject=0, build_start_pos:Vector3=None, source_bag:c_int=None, source_id:c_int64=None, source_lot:c_int=None, source_type:c_int=None, target_id:c_int64=None, target_lot:c_int=None, target_pos:Vector3=None, target_type:c_int=None):
|
||||
self.object.inventory.push_equipped_items_state()
|
||||
|
||||
@@ -11,7 +11,6 @@ from ..mission import check_prereqs, MissionProgress, MissionState, ObtainItemTy
|
||||
|
||||
class CharMission:
|
||||
def __init__(self):
|
||||
self.autocomplete_missions = False
|
||||
self.missions = PersistentMapping()
|
||||
# add achievements
|
||||
for mission_id, data in server.db.missions.items():
|
||||
|
||||
@@ -5,12 +5,12 @@ from ...messages import single
|
||||
|
||||
class CharUI:
|
||||
@single
|
||||
def display_message_box(self, show:bool=None, callback_client:GameObject=None, identifier:str=None, image_id:c_int=None, text:str=None, user_data:str=None):
|
||||
def display_message_box(self, show:bool=None, callback_client:GameObject=None, id:str=None, image_id:c_int=None, text:str=None, user_data:str=None):
|
||||
pass
|
||||
|
||||
def disp_message_box(self, text):
|
||||
def disp_message_box(self, text, id="", callback=None):
|
||||
"""display_message_box with default parameters."""
|
||||
self.display_message_box(show=True, callback_client=None, identifier="", image_id=0, text=text, user_data="")
|
||||
self.display_message_box(show=True, callback_client=callback, id=id, image_id=0, text=text, user_data="")
|
||||
|
||||
@single
|
||||
def display_tooltip(self, do_or_die:bool=False, no_repeat:bool=False, no_revive:bool=False, is_property_tooltip:bool=False, show:bool=None, translate:bool=False, time:c_int=None, id:str=None, localize_params:LDF=None, image_name:str=None, text:str=None):
|
||||
|
||||
@@ -31,6 +31,6 @@ class Comp108Component(Component):
|
||||
if self.driver_id != 0:
|
||||
server.game_objects[self.driver_id].char.dismount()
|
||||
|
||||
def request_die(self, unknown_bool:bool=None, death_type:str=None, direction_relative_angle_xz:float=None, direction_relative_angle_y:float=None, direction_relative_force:float=None, kill_type:c_int=0, killer:GameObject=None, loot_owner:GameObject=0):
|
||||
def request_die(self, unknown_bool:bool=None, death_type:str=None, direction_relative_angle_xz:float=None, direction_relative_angle_y:float=None, direction_relative_force:float=None, kill_type:c_int=0, killer:GameObject=None, loot_owner:GameObject=None):
|
||||
#self.object.destructible.deal_damage(10000, self) # die permanently on crash
|
||||
self.object.call_later(3, self.object.destructible.resurrect)
|
||||
|
||||
@@ -46,11 +46,11 @@ class DestructibleComponent(Component):
|
||||
self.object.stats.life = max(0, self.object.stats.life - (damage - self.object.stats.armor))
|
||||
self.object.stats.armor = max(0, self.object.stats.armor - damage)
|
||||
|
||||
def simply_die(self, death_type:str="", kill_type:c_int=KillType.Violent, killer:GameObject=None, loot_owner:GameObject=0):
|
||||
def simply_die(self, death_type:str="", kill_type:c_int=KillType.Violent, killer:GameObject=None, loot_owner:GameObject=None):
|
||||
"""Shorthand for request_die with default values."""
|
||||
self.request_die(False, death_type, 0, 0, 10, kill_type, killer, loot_owner)
|
||||
|
||||
def request_die(self, unknown_bool:bool=None, death_type:str=None, direction_relative_angle_xz:float=None, direction_relative_angle_y:float=None, direction_relative_force:float=None, kill_type:c_int=KillType.Violent, killer:GameObject=None, loot_owner:GameObject=0):
|
||||
def request_die(self, unknown_bool:bool=None, death_type:str=None, direction_relative_angle_xz:float=None, direction_relative_angle_y:float=None, direction_relative_force:float=None, kill_type:c_int=KillType.Violent, killer:GameObject=None, loot_owner:GameObject=None):
|
||||
if self.object.stats.life == 0:
|
||||
# already dead
|
||||
return
|
||||
|
||||
@@ -58,7 +58,6 @@ class MissionProgress(Persistent):
|
||||
self.tasks = [MissionTask(task_type, target, target_value, parameter) for task_type, target, target_value, parameter in mission_data[2]]
|
||||
self.is_mission = mission_data[3]
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import random
|
||||
|
||||
@@ -66,7 +65,6 @@ from ..bitstream import c_int
|
||||
from ..game_object import GameObject
|
||||
from ..messages import single
|
||||
from ..world import server
|
||||
from ..commands.mission import CompleteMission
|
||||
from .component import Component
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -149,9 +147,6 @@ class MissionNPCComponent(Component):
|
||||
if mission_state == MissionState.Available:
|
||||
assert not is_complete
|
||||
player.char.add_mission(mission_id)
|
||||
if player.char.autocomplete_missions:
|
||||
asyncio.get_event_loop().call_soon(CompleteMission.async_complete_mission, CompleteMission, mission_id, False, player)
|
||||
|
||||
elif mission_state == MissionState.ReadyToComplete:
|
||||
assert is_complete
|
||||
player.char.complete_mission(mission_id)
|
||||
|
||||
@@ -36,31 +36,11 @@ class PhysicsComponent(Component):
|
||||
for comp in self.object.components:
|
||||
if hasattr(comp, "on_enter") or hasattr(comp, "on_exit"):
|
||||
server.general.tracked_objects[self.object] = CollisionSphere(self.object, radius)
|
||||
if server.get_objects_in_group("physics_debug_marker"):
|
||||
self.spawn_debug_marker()
|
||||
if "proximity_radius" in server._handlers:
|
||||
for handler in server._handlers["proximity_radius"]:
|
||||
handler(self)
|
||||
break
|
||||
|
||||
def spawn_debug_marker(self):
|
||||
if self.object not in server.general.tracked_objects:
|
||||
return
|
||||
coll = server.general.tracked_objects[self.object]
|
||||
set_vars = {"groups": ("physics_debug_marker",), "parent": self.object, "rotation": Quaternion.identity}
|
||||
if isinstance(coll, AABB):
|
||||
config = LDF()
|
||||
config.ldf_set("primitiveModelType", LDFDataType.INT32, PrimitiveModelType.Cuboid)
|
||||
config.ldf_set("primitiveModelValueX", LDFDataType.FLOAT, coll.max.x-coll.min.x)
|
||||
config.ldf_set("primitiveModelValueY", LDFDataType.FLOAT, coll.max.y-coll.min.y)
|
||||
config.ldf_set("primitiveModelValueZ", LDFDataType.FLOAT, coll.max.z-coll.min.z)
|
||||
|
||||
set_vars["position"] = Vector3((coll.min.x+coll.max.x)/2, coll.min.y, (coll.min.z+coll.max.z)/2)
|
||||
set_vars["config"] = config
|
||||
server.spawn_object(14510, set_vars)
|
||||
elif isinstance(coll, CollisionSphere):
|
||||
set_vars["position"] = coll.position
|
||||
set_vars["scale"] = math.sqrt(coll.sq_radius)/5
|
||||
server.spawn_object(6548, set_vars)
|
||||
|
||||
|
||||
# not really related to physics, but depends on physics and hasn't been conclusively associated with a component
|
||||
|
||||
def drop_rewards(self, loot_matrix, currency_min, currency_max, owner):
|
||||
@@ -339,8 +319,6 @@ class PhantomPhysicsComponent(PhysicsComponent):
|
||||
continue
|
||||
if hasattr(comp, "on_enter") or hasattr(comp, "on_exit"):
|
||||
server.general.tracked_objects[self.object] = AABB(self.object)
|
||||
if server.get_objects_in_group("physics_debug_marker"):
|
||||
self.spawn_debug_marker()
|
||||
break
|
||||
|
||||
def on_enter(self, player):
|
||||
|
||||
@@ -44,8 +44,8 @@ class ScriptedActivityComponent(Component):
|
||||
def activity_start(self):
|
||||
pass
|
||||
|
||||
def message_box_respond(self, player, button:c_int=None, identifier:str=None, user_data:str=None):
|
||||
if identifier == "LobbyReady" and button == 1:
|
||||
def message_box_respond(self, player, button:c_int=None, id:str=None, user_data:str=None):
|
||||
if id == "LobbyReady" and button == 1:
|
||||
asyncio.ensure_future(player.char.transfer_to_world((self.transfer_world_id, 0, 0)))
|
||||
|
||||
@single
|
||||
|
||||
@@ -17,7 +17,9 @@ class GameObject:
|
||||
self.attr_changed(name)
|
||||
super().__setattr__(name, value)
|
||||
|
||||
def __init__(self, lot, object_id, set_vars={}):
|
||||
def __init__(self, lot, object_id, set_vars=None):
|
||||
if set_vars is None:
|
||||
set_vars = {}
|
||||
self._handlers = {}
|
||||
self._flags = {}
|
||||
self._flags["parent_flag"] = "related_objects_flag"
|
||||
@@ -81,11 +83,19 @@ class GameObject:
|
||||
for component_type, component_id in sorted(comp_ids, key=lambda x: component_order.index(x[0]) if x[0] in component_order else 99999):
|
||||
if component_type == 5:
|
||||
if "custom_script" in set_vars and set_vars["custom_script"] is not None:
|
||||
script = importlib.import_module("luserver.scripts."+set_vars["custom_script"])
|
||||
comp = script.ScriptComponent,
|
||||
try:
|
||||
script = importlib.import_module("luserver.scripts."+set_vars["custom_script"])
|
||||
comp = script.ScriptComponent,
|
||||
except ModuleNotFoundError as e:
|
||||
log.warning(str(e))
|
||||
comp = ScriptComponent,
|
||||
elif component_id is not None and component_id in server.db.script_component:
|
||||
script = importlib.import_module("luserver.scripts."+server.db.script_component[component_id])
|
||||
comp = script.ScriptComponent,
|
||||
try:
|
||||
script = importlib.import_module("luserver.scripts."+server.db.script_component[component_id])
|
||||
comp = script.ScriptComponent,
|
||||
except ModuleNotFoundError as e:
|
||||
log.warning(str(e))
|
||||
comp = ScriptComponent,
|
||||
else:
|
||||
comp = ScriptComponent,
|
||||
elif component_type in component:
|
||||
|
||||
@@ -194,6 +194,7 @@ class GameMessage(Enum):
|
||||
BounceNotification = 932
|
||||
BBBSaveRequest = 1001
|
||||
NotifyClientObject = 1042
|
||||
DisplayZoneSummary = 1043
|
||||
StartBuildingWithItem = 1057
|
||||
StartArrangingWithItem = 1061
|
||||
FinishArrangingWithItem = 1062
|
||||
|
||||
@@ -19,7 +19,7 @@ log = logging.getLogger(__name__)
|
||||
|
||||
# Constant checksums that the client expects to verify map version
|
||||
# (likely value of the last map revision)
|
||||
checksum = {
|
||||
_CHECKSUMS = {
|
||||
World.VentureExplorer: 0x20b8087c,
|
||||
World.ReturnToTheVentureExplorer: 0x26680a3c,
|
||||
World.AvantGardens: 0x49525511,
|
||||
@@ -57,22 +57,11 @@ class GeneralHandling:
|
||||
def __init__(self):
|
||||
server.general = self
|
||||
self.tracked_objects = {}
|
||||
physics_debug_cmd = server.chat.commands.add_parser("physicsdebug")
|
||||
physics_debug_cmd.set_defaults(func=self.physics_debug_cmd)
|
||||
|
||||
server.register_handler(WorldServerMsg.LoadComplete, self.on_client_load_complete)
|
||||
server.register_handler(WorldServerMsg.PositionUpdate, self.on_position_update)
|
||||
server.register_handler(WorldServerMsg.GameMessage, self.on_game_message)
|
||||
|
||||
def physics_debug_cmd(self, args, sender):
|
||||
debug_markers = server.get_objects_in_group("physics_debug_marker")
|
||||
if not debug_markers:
|
||||
for obj in self.tracked_objects.copy():
|
||||
obj.physics.spawn_debug_marker()
|
||||
else:
|
||||
for marker in debug_markers:
|
||||
server.replica_manager.destruct(marker)
|
||||
|
||||
def on_validated(self, address):
|
||||
player = server.accounts[address].characters.selected()
|
||||
if server.world_id[0] != 0:
|
||||
@@ -100,7 +89,7 @@ class GeneralHandling:
|
||||
load_world.write(c_ushort(world_id))
|
||||
load_world.write(c_ushort(world_instance))
|
||||
load_world.write(c_uint(world_clone))
|
||||
load_world.write(c_uint(checksum.get(World(world_id), 0)))
|
||||
load_world.write(c_uint(_CHECKSUMS.get(World(world_id), 0)))
|
||||
load_world.write(bytes(2))
|
||||
load_world.write(c_float(player.physics.position.x))
|
||||
load_world.write(c_float(player.physics.position.y))
|
||||
|
||||
@@ -10,4 +10,4 @@ class ScriptComponent(script.ScriptComponent):
|
||||
assert multi_interact_id is None
|
||||
player.char.set_flag(True, FLAG_ID)
|
||||
player.inventory.remove_item(InventoryType.Items, lot=MAELSTROM_CUBE_LOT)
|
||||
server.get_objects_in_group("cagedSpider")[0].script.fire_event_client_side(args="toggle", obj=None, sender=player)
|
||||
server.get_objects_in_group("cagedSpider")[0].script.fire_event_client_side(args="toggle", obj=None, sender=player, player=player)
|
||||
|
||||
14
luserver/scripts/avant_gardens/caged_spider.py
Normal file
14
luserver/scripts/avant_gardens/caged_spider.py
Normal file
@@ -0,0 +1,14 @@
|
||||
import luserver.components.script as script
|
||||
from luserver.bitstream import c_int, c_int64
|
||||
from luserver.game_object import GameObject
|
||||
from luserver.messages import single
|
||||
|
||||
class ScriptComponent(script.ScriptComponent):
|
||||
# hacky workaround incoming:
|
||||
# the clientside implementation is broken and doesn't check the sender param
|
||||
# so the cinematic would get displayed for everyone since this message is broadcast
|
||||
# easiest fix is to override it for this script to be single instead
|
||||
# other option would be to allow broadcast messages to be single per-call, but that seems like even more of a hack
|
||||
@single
|
||||
def fire_event_client_side(self, args:str=None, obj:GameObject=None, param1:c_int64=0, param2:c_int=-1, sender:GameObject=None):
|
||||
pass
|
||||
@@ -1,6 +1,7 @@
|
||||
import luserver.components.script as script
|
||||
from luserver.bitstream import c_int
|
||||
from luserver.game_object import GameObject
|
||||
from luserver.messages import single
|
||||
from luserver.components.inventory import InventoryType
|
||||
from luserver.components.mission import MissionState
|
||||
|
||||
@@ -13,3 +14,10 @@ class ScriptComponent(script.ScriptComponent):
|
||||
player.char.complete_mission(1729)
|
||||
elif mission_state == MissionState.ReadyToComplete:
|
||||
player.inventory.remove_item(InventoryType.Items, lot=14397)
|
||||
self.notify_client_object(name="switch", param1=0, param2=0, param_str=b"", param_obj=None, player=player)
|
||||
|
||||
# manually changed from broadcast to single because the client script abuses this message
|
||||
# see also caged_spider
|
||||
@single
|
||||
def notify_client_object(self, name:str=None, param1:c_int=None, param2:c_int=None, param_obj:GameObject=None, param_str:bytes=None):
|
||||
pass
|
||||
|
||||
@@ -128,11 +128,11 @@ class ScriptComponent(script.ScriptComponent):
|
||||
|
||||
self.set_player_spawn_points()
|
||||
|
||||
def message_box_respond(self, player, button:c_int=None, identifier:str=None, user_data:str=None):
|
||||
if identifier == "RePlay":
|
||||
def message_box_respond(self, player, button:c_int=None, id:str=None, user_data:str=None):
|
||||
if id == "RePlay":
|
||||
self.start()
|
||||
|
||||
elif identifier == "Exit_Question" and button == 1:
|
||||
elif id == "Exit_Question" and button == 1:
|
||||
self.game_over(player)
|
||||
self.object.scripted_activity.remove_player(player)
|
||||
asyncio.ensure_future(player.char.transfer_to_last_non_instance(Vector3(131.83, 376, -180.31), Quaternion(0, -0.268720, 0, 0.963218)))
|
||||
|
||||
10
luserver/scripts/general/console_teleport.py
Normal file
10
luserver/scripts/general/console_teleport.py
Normal file
@@ -0,0 +1,10 @@
|
||||
import asyncio
|
||||
|
||||
import luserver.components.script as script
|
||||
|
||||
# todo: not completely implemented
|
||||
|
||||
class ScriptComponent(script.ScriptComponent):
|
||||
def transfer(self, player, world, respawn_point_name):
|
||||
player.render.play_animation("lup-teleport")
|
||||
asyncio.get_event_loop().call_later(4, asyncio.ensure_future, player.char.transfer_to_world(world, respawn_point_name=respawn_point_name))
|
||||
21
luserver/scripts/general/teleport_to_ns_or_nt.py
Normal file
21
luserver/scripts/general/teleport_to_ns_or_nt.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import luserver.scripts.general.console_teleport as script
|
||||
from luserver.amf3 import AMF3
|
||||
from luserver.bitstream import c_int
|
||||
from luserver.world import server
|
||||
from luserver.components.char import TerminateType
|
||||
# todo: implement visited worlds so the NS/NT choice UI can work
|
||||
|
||||
class ScriptComponent(script.ScriptComponent):
|
||||
def on_use(self, player, multi_interact_id):
|
||||
assert multi_interact_id is None
|
||||
# todo: check if player has been to NT, if yes then display choice UI
|
||||
player.char.disp_message_box(id="TransferBox", text="UI_TRAVEL_TO_LUP_STATION", callback=self.object)
|
||||
|
||||
def message_box_respond(self, player, button:c_int=None, id:str=None, user_data:str=None):
|
||||
if id == "TransferBox":
|
||||
if button == 1:
|
||||
# todo: display zone summary (callback not working right now for some reason)
|
||||
#player.char.display_zone_summary(sender=self.object)
|
||||
self.transfer(player, (1200, 0, 0), "NS_LEGO_Club")
|
||||
else:
|
||||
player.char.terminate_interaction(terminator=self.object, type=TerminateType.FromInteraction)
|
||||
@@ -6,8 +6,8 @@ from luserver.bitstream import c_int
|
||||
class ScriptComponent(script.ScriptComponent):
|
||||
def on_use(self, player, multi_interact_id):
|
||||
assert multi_interact_id is None
|
||||
player.char.display_message_box(show=True, callback_client=self.object, identifier="instance_exit", image_id=0, text=self.script_vars.get("transfer_text", "DRAGON_EXIT_QUESTION"), user_data="")
|
||||
player.char.display_message_box(show=True, callback_client=self.object, id="instance_exit", image_id=0, text=self.script_vars.get("transfer_text", "DRAGON_EXIT_QUESTION"), user_data="")
|
||||
|
||||
def message_box_respond(self, player, button:c_int=None, identifier:str=None, user_data:str=None):
|
||||
if identifier == "instance_exit" and button == 1:
|
||||
def message_box_respond(self, player, button:c_int=None, id:str=None, user_data:str=None):
|
||||
if id == "instance_exit" and button == 1:
|
||||
asyncio.ensure_future(player.char.transfer_to_last_non_instance())
|
||||
|
||||
28
luserver/scripts/nimbus_station/lego_club_door.py
Normal file
28
luserver/scripts/nimbus_station/lego_club_door.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import luserver.scripts.general.teleport_to_ns_or_nt as script
|
||||
from luserver.amf3 import AMF3
|
||||
from luserver.bitstream import c_int
|
||||
from luserver.world import server
|
||||
from luserver.components.char import TerminateType
|
||||
|
||||
# todo: not completely implemented
|
||||
# todo: implement visited worlds so the NS/NT choice UI can work
|
||||
|
||||
class ScriptComponent(script.ScriptComponent):
|
||||
def on_use(self, player, multi_interact_id):
|
||||
assert multi_interact_id is None
|
||||
if server.world_id[0] == 1700:
|
||||
# todo: check if player has been to NT, if yes then display choice UI
|
||||
player.char.disp_message_box(id="TransferBox", text="UI_TRAVEL_TO_NS", callback=self.object)
|
||||
else:
|
||||
player.char.u_i_message_server_to_single_client(message_name=b"pushGameState", args=AMF3({"state": "Lobby", "context": {"user": str(player.object_id), "callbackObj": str(self.object.object_id), "HelpVisible": "show", "type": "Lego_Club_Valid"}}))
|
||||
|
||||
def message_box_respond(self, player, button:c_int=None, id:str=None, user_data:str=None):
|
||||
if id == "PlayButton":
|
||||
self.transfer(player, (1700, 0, 0), "")
|
||||
elif id == "TransferBox":
|
||||
if button == 1:
|
||||
# todo: display zone summary (callback not working right now for some reason)
|
||||
#player.char.display_zone_summary(sender=self.object)
|
||||
self.transfer(player, (1200, 0, 0), "NS_LEGO_Club")
|
||||
else:
|
||||
player.char.terminate_interaction(terminator=self.object, type=TerminateType.FromInteraction)
|
||||
35
luserver/scripts/nimbus_station/lup_teleport.py
Normal file
35
luserver/scripts/nimbus_station/lup_teleport.py
Normal file
@@ -0,0 +1,35 @@
|
||||
import asyncio
|
||||
|
||||
import luserver.scripts.general.teleport_to_ns_or_nt as script
|
||||
from luserver.amf3 import AMF3
|
||||
from luserver.bitstream import c_int
|
||||
from luserver.world import server
|
||||
from luserver.components.char import TerminateType
|
||||
|
||||
# todo: not completely implemented
|
||||
# todo: implement visited worlds so the NS/NT choice UI can work
|
||||
|
||||
class ScriptComponent(script.ScriptComponent):
|
||||
def on_use(self, player, multi_interact_id):
|
||||
assert multi_interact_id is None
|
||||
# todo: check if player has been to NT, if yes then display choice UI
|
||||
if server.world_id[0] == 1600:
|
||||
text = "UI_TRAVEL_TO_NS"
|
||||
else:
|
||||
text = "UI_TRAVEL_TO_LUP_STATION"
|
||||
player.char.disp_message_box(id="TransferBox", text=text, callback=self.object)
|
||||
|
||||
def message_box_respond(self, player, button:c_int=None, id:str=None, user_data:str=None):
|
||||
if id == "TransferBox":
|
||||
if button == 1:
|
||||
# todo: display zone summary (callback not working right now for some reason)
|
||||
#player.char.display_zone_summary(sender=self.object)
|
||||
if server.world_id[0] == 1600:
|
||||
dest = 1200
|
||||
spawnpoint = "NS_LW"
|
||||
else:
|
||||
dest = 1600
|
||||
spawnpoint = ""
|
||||
self.transfer(player, (dest, 0, 0), spawnpoint)
|
||||
else:
|
||||
player.char.terminate_interaction(terminator=self.object, type=TerminateType.FromInteraction)
|
||||
@@ -116,6 +116,7 @@ class WorldServer(Server):
|
||||
self.not_console_logged_packets.add("GameMessage/ReadyForUpdates")
|
||||
self.not_console_logged_packets.add("GameMessage/ScriptNetworkVarUpdate")
|
||||
self.multi = MultiInstanceAccess()
|
||||
self._handlers = {}
|
||||
CharHandling()
|
||||
ChatHandling()
|
||||
GeneralHandling()
|
||||
@@ -199,6 +200,19 @@ class WorldServer(Server):
|
||||
lot, position, rotation = spawn_data
|
||||
self.spawn_model(spawner_id, lot, position, rotation)
|
||||
|
||||
EVENT_NAMES = "proximity_radius"
|
||||
def add_handler(self, event_name: str, handler):
|
||||
if event_name not in WorldServer.EVENT_NAMES:
|
||||
raise ValueError("Invalid event name %s", event_name)
|
||||
self._handlers.setdefault(event_name, []).append(handler)
|
||||
|
||||
def remove_handler(self, event_name: str, handler):
|
||||
if event_name not in WorldServer.EVENT_NAMES:
|
||||
raise ValueError("Invalid event name %s", event_name)
|
||||
if event_name not in self._handlers or handler not in self._handlers[event_name]:
|
||||
raise RuntimeError("handler not found")
|
||||
self._handlers[event_name].remove(handler)
|
||||
|
||||
def spawn_model(self, spawner_id, lot, position, rotation):
|
||||
spawned_vars = {}
|
||||
spawned_vars["position"] = position
|
||||
|
||||
@@ -284,13 +284,10 @@ class Init:
|
||||
self.root.components_registry.setdefault(row[0], []).append((row[1], row[2]))
|
||||
|
||||
if row[1] == 5 and row[2] not in self.root.script_component:
|
||||
comp_row = self.cdclient.execute("select id, script_name from ScriptComponent where id == %i" % row[2]).fetchone()
|
||||
if comp_row is None:
|
||||
continue
|
||||
id, script_name = comp_row
|
||||
script_name = scripts.SCRIPTS.get(id)
|
||||
if script_name is not None:
|
||||
self.root.script_component[id] = script_name
|
||||
# we don't even need to query the db since we've got our own scripts table
|
||||
script_id = row[2]
|
||||
if script_id in scripts.SCRIPTS:
|
||||
self.root.script_component[script_id] = scripts.SCRIPTS[script_id]
|
||||
|
||||
elif row[1] == 7 and row[2] not in self.root.destructible_component:
|
||||
faction, faction_list, level, loot_matrix_index, currency_index, life, armor, imagination, is_smashable = self.cdclient.execute("select faction, factionList, level, LootMatrixIndex, CurrencyIndex, life, armor, imagination, isSmashable from DestructibleComponent where id == %i" % row[2]).fetchone()
|
||||
|
||||
@@ -16,6 +16,7 @@ SCRIPTS = {
|
||||
847: "avant_gardens.rusty_steele",
|
||||
849: "nimbus_station.concert_quickbuild",
|
||||
867: "avant_gardens.survival.buff_station",
|
||||
877: "avant_gardens.caged_spider",
|
||||
882: "avant_gardens.survival.world_control",
|
||||
901: "avant_gardens.survival.stromling_mech",
|
||||
946: "gnarled_forest.torch",
|
||||
@@ -43,10 +44,11 @@ SCRIPTS = {
|
||||
1216: "items.cauldron_of_life",
|
||||
1218: "items.anvil_of_armor",
|
||||
1219: "items.fountain_of_imagination",
|
||||
1239: "nimbus_station.lego_club_door",
|
||||
1270: "avant_gardens.saluting_npcs",
|
||||
1271: "avant_gardens.saluting_npcs",
|
||||
1272: "avant_gardens.saluting_npcs",
|
||||
1276: "general.transfer_world_on_use",
|
||||
1276: "nimbus_station.lup_teleport",
|
||||
1329: "crux_prime.aura_blossom_flower",
|
||||
1345: "general.poi_mission",
|
||||
1349: "crux_prime.scroll_shrine",
|
||||
@@ -54,8 +56,8 @@ SCRIPTS = {
|
||||
1419: "nexus_tower.water_fountain",
|
||||
1458: "items.sunflower",
|
||||
1481: "nexus_tower.vault",
|
||||
1484: "general.transfer_world_on_use",
|
||||
1485: "general.transfer_world_on_use",
|
||||
1484: "nimbus_station.lup_teleport",
|
||||
1485: "nimbus_station.lego_club_door",
|
||||
1486: "general.transfer_world_on_use",
|
||||
1519: "nexus_tower.venture_cannon",
|
||||
1527: "general.transfer_world_on_use",
|
||||
@@ -86,6 +88,7 @@ SCRIPTS = {
|
||||
r"02_server\Map\General\L_FRICTION_VOLUME_SERVER.lua": "general.friction_volume",
|
||||
r"02_server\Map\General\L_POI_MISSION.lua": "general.poi_mission",
|
||||
r"02_server\Map\General\L_TOUCH_MISSION_UPDATE_SERVER.lua": "general.touch_complete_mission",
|
||||
r"02_server\Map\NS\L_NS_LUP_TELEPORT.lua": "nimbus_station.lup_teleport",
|
||||
r"02_server\Map\NS\L_NS_TOKEN_CONSOLE_SERVER.lua": "nimbus_station.token_console",
|
||||
r"02_server\Map\NT\L_NT_ASSEMBLYTUBE_SERVER.lua": "nexus_tower.assembly_tube",
|
||||
r"02_server\Map\NT\L_NT_PARADOXTELE_SERVER.lua": "nexus_tower.paradox_teleporter",
|
||||
@@ -109,3 +112,4 @@ SCRIPTS = {
|
||||
r"ai\NS\L_NS_MODULAR_BUILD.lua": "nimbus_station.rocket_modular_build",
|
||||
r"ai\NS\L_NS_QB_IMAGINATION_STATUE.lua": "nimbus_station.imagination_statue",
|
||||
r"ai\NS\NS_PP_01\L_NS_PP_01_TELEPORT.lua": "property.teleport"}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user