duck123
Recruit
Here is a video I made that talks about getting custom scripts in the scene editor to work on a multiplayer server. Ive attached the code examples from the video. I made a similar post earlier for getting scripts to run just in single player: https://forums.taleworlds.com/index...s-to-use-in-scene-editor.454338/#post-9833789.
You must add the module to your start server command: .\DedicatedCustomServer.Starter.exe /dedicatedcustomserverconfigfile ds_config_duel_Pontoon.txt _MODULES_*Native*Multiplayer*MyMods*_MODULES_
You must put your module dll in the right location: C:\Program Files (x86)\Steam\steamapps\common\Mount & Blade II Dedicated Server\Modules\MyMods\bin\Win64_Shipping_Server
Here is my submodule.xml from my server as an example of how to set that for the custom script dll.
You must add the module to your start server command: .\DedicatedCustomServer.Starter.exe /dedicatedcustomserverconfigfile ds_config_duel_Pontoon.txt _MODULES_*Native*Multiplayer*MyMods*_MODULES_
You must put your module dll in the right location: C:\Program Files (x86)\Steam\steamapps\common\Mount & Blade II Dedicated Server\Modules\MyMods\bin\Win64_Shipping_Server
Here is my submodule.xml from my server as an example of how to set that for the custom script dll.
XML:
<Module>
<Name value="MyMods"/>
<Id value="MyMods"/>
<Version value="v1.0.2"/>
<DefaultModule value="false"/>
<ModuleCategory value="Multiplayer"/>
<Official value="false"/>
<DependedModules>
<DependedModule Id="Native" DependentVersion="v1.0.2" Optional="false"/>
</DependedModules>
<SubModules>
<SubModule>
<Name value="MyMods"/>
<DLLName value="MyMods.dll"/>
<SubModuleClassType value="MyMods.Main"/>
<Tags>
<Tag key="DedicatedServerType" value="custom" />
</Tags>
</SubModule>
</SubModules>
<Xmls>
</Xmls>
</Module>
C#:
using NetworkMessages.FromServer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TaleWorlds.Engine;
using TaleWorlds.Library;
using TaleWorlds.MountAndBlade;
namespace MyMods
{
public class CS_MoveBackAndForth : SynchedMissionObject
{
public bool EnabledInGame = false;
public bool EnabledInEditor = false;
public float Destination_X1 = 0f;
public float Destination_Y1 = 0f;
public float Destination_Z1 = 0f;
public float Destination_X2 = 0f;
public float Destination_Y2 = 0f;
public float Destination_Z2 = 0f;
public float MoveSpeedX = 0f;
public float MoveSpeedY = 0f;
public float MoveSpeedZ = 0f;
public float SlowAtDist = 0f;
public float SlowSpeedPercent = 0f;
private bool FirstRun = true;
private bool GoToDest1 = true;
private bool DestXGreater = true;
private bool DestYGreater = true;
private bool DestZGreater = true;
private float sixtyFpsFrameTime = 0.0166f;
private SynchedMissionObject Platform;
private bool editorEntitySet = false;
private void Move(float dt)
{
float frameTime = dt;
// We need to compensate for frame differences vs my standard 60 fps. Need to figure out what fps the server uses.
float movementFrameModifier = frameTime / sixtyFpsFrameTime;
if (GoToDest1 == true)
{
MakeMove(Destination_X1, Destination_Y1, Destination_Z1, movementFrameModifier);
}
else
{
MakeMove(Destination_X2, Destination_Y2, Destination_Z2, movementFrameModifier);
}
}
private void MakeMove(float Destination_X, float Destination_Y, float Destination_Z, float movementFrameModifier)
{
float curPositionX = this.Platform.GameEntity.GetFrame().origin.x;
float curPositionY = this.Platform.GameEntity.GetFrame().origin.y;
float curPositionZ = this.Platform.GameEntity.GetFrame().origin.z;
bool reachedDestination = false;
float movementX = MoveSpeedX * movementFrameModifier, movementY = MoveSpeedY * movementFrameModifier, movementZ = MoveSpeedZ * movementFrameModifier;
// Set compare types for first run in current route to destination
if (FirstRun)
{
if (curPositionX >= Destination_X)
{
DestXGreater = false;
}
if (curPositionY >= Destination_Y)
{
DestYGreater = false;
}
if (curPositionZ >= Destination_Z)
{
DestZGreater = false;
}
FirstRun = false;
}
/////////////////////////////////////
// Do compares based on compare types we set to see what direction we move or if we are done
movementX = DetermineMovement(movementX, curPositionX, Destination_X, DestXGreater);
movementY = DetermineMovement(movementY, curPositionY, Destination_Y, DestYGreater);
movementZ = DetermineMovement(movementZ, curPositionZ, Destination_Z, DestZGreater);
///////////////////////////////////////////////////
// Check if we have reached destination
if (movementX == 0f && movementY == 0f && movementZ == 0f)
{
reachedDestination = true;
}
//////////////////////////////////////////////
// If we have reached our destination then setup for going to the other destination and return
if (reachedDestination == true)
{
GoToDest1 = !GoToDest1;
FirstRun = true;
DestXGreater = true;
DestYGreater = true;
DestZGreater = true;
return;
}
//////////////////////////////////////////////////////////////
// Do the actual vector move for the entity
Vec3 vec = new Vec3(movementX, movementY, movementZ, -1f);
MatrixFrame frame = this.Platform.GameEntity.GetFrame();
frame.origin += vec;
if (GameNetwork.IsServer)
{
this.Platform.SetFrameSynched(ref frame, false);
}
else
{
this.Platform.GameEntity.SetFrame(ref frame);
}
}
private float DetermineMovement(float movement, float curPosition, float destination, bool DestGreater)
{
if (DestGreater == true)
{
if (destination <= curPosition)
{
movement *= 0f;
}
else if (destination <= (curPosition + SlowAtDist))
{
movement *= SlowSpeedPercent;
}
}
else
{
movement *= -1f;
if (destination >= curPosition)
{
movement *= 0f;
}
else if (destination >= (curPosition - SlowAtDist))
{
movement *= SlowSpeedPercent;
}
}
return movement;
}
public bool NetworkLog(NetworkCommunicator networkPeer, string message)
{
GameNetwork.BeginModuleEventAsServer(networkPeer);
GameNetwork.WriteMessage(new ServerMessage(message));
GameNetwork.EndModuleEventAsServer();
return true;
}
public override ScriptComponentBehavior.TickRequirement GetTickRequirement()
{
return ScriptComponentBehavior.TickRequirement.Tick | base.GetTickRequirement();
}
protected override void OnInit()
{
base.OnInit();
base.SetScriptComponentToTick(this.GetTickRequirement());
GameEntity tempEntity = this.GameEntity.CollectChildrenEntitiesWithTag("child_mover").SingleOrDefault<GameEntity>();
if (tempEntity != null)
{
this.Platform = tempEntity.GetScriptComponents<SynchedMissionObject>().SingleOrDefault<SynchedMissionObject>();
}
}
protected override void OnTick(float dt)
{
if(this.Platform == null)
{
return;
}
if (EnabledInGame == true)
{
if (GameNetwork.IsMultiplayer)
{
if (GameNetwork.IsServer)
{
this.Move(dt);
}
}
else
{
this.Move(dt);
}
}
}
protected override void OnEditorTick(float dt)
{
base.OnEditorTick(dt);
//InformationManager.DisplayMessage(new InformationMessage("step 0"));
GameEntity tempEntity = this.GameEntity.CollectChildrenEntitiesWithTag("child_mover").SingleOrDefault<GameEntity>();
if (tempEntity != null)
{
this.Platform = tempEntity.GetScriptComponents<SynchedMissionObject>().SingleOrDefault<SynchedMissionObject>();
editorEntitySet = true;
} else
{
editorEntitySet = false;
}
if (this.Platform == null)
{
return;
}
if (EnabledInEditor == true && editorEntitySet == true)
{
this.Move(dt);
}
}
}
}
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TaleWorlds.Engine;
using TaleWorlds.Library;
using TaleWorlds.MountAndBlade;
using TaleWorlds.Core;
using NetworkMessages.FromServer;
using TaleWorlds.Diamond.ChatSystem.Library;
namespace MyMods
{
public class CS_DamageZone : ScriptComponentBehavior
{
public bool EnabledInGame = false;
public int InflictedDamage = 0;
public float DamageTimeInterval = 1.000f;
protected float Max_x = 0.0f;
protected float Min_x = 0.0f;
protected float Max_y = 0.0f;
protected float Min_y = 0.0f;
protected float Max_z = 0.0f;
protected float Min_z = 0.0f;
protected float timeInZone = 0.0f;
private void CheckIfInDamageZone(float frameTime)
{
Vec3 agentPosition;
Blow blow = new Blow();
timeInZone += frameTime;
if (timeInZone < DamageTimeInterval)
{
return;
}
else
{
timeInZone = 0f;
}
foreach (Agent gameAgent in Mission.Current.Agents.ToList())
{
agentPosition = gameAgent.GetChestGlobalPosition();
if (agentPosition.x > Min_x && agentPosition.x < Max_x && agentPosition.y > Min_y && agentPosition.y < Max_y && agentPosition.z > Min_z && agentPosition.z < Max_z)
{
blow = new Blow(gameAgent.Index);
blow.DamageType = DamageTypes.Blunt;
blow.BoneIndex = gameAgent.Monster.HeadLookDirectionBoneIndex;
blow.Position = gameAgent.Position;
blow.Position.z = blow.Position.z + gameAgent.GetEyeGlobalHeight();
blow.WeaponRecord.FillAsMeleeBlow(null, null, -1, -1);
blow.InflictedDamage = InflictedDamage;
blow.SwingDirection = gameAgent.LookDirection;
MatrixFrame frame = gameAgent.Frame;
blow.SwingDirection = frame.rotation.TransformToParent(new Vec3(-1f, 0f, 0f, -1f));
blow.SwingDirection.Normalize();
blow.Direction = blow.SwingDirection;
blow.DamageCalculated = true;
sbyte mainHandItemBoneIndex = gameAgent.Monster.MainHandItemBoneIndex;
AttackCollisionData attackCollisionDataForDebugPurpose = AttackCollisionData.GetAttackCollisionDataForDebugPurpose(false, false, false, true, false, false, false, false, false, false, false, false, CombatCollisionResult.StrikeAgent, -1, 0, 2, blow.BoneIndex, BoneBodyPartType.Head, mainHandItemBoneIndex, Agent.UsageDirection.AttackLeft, -1, CombatHitResultFlags.NormalHit, 0.5f, 1f, 0f, 0f, 0f, 0f, 0f, 0f, Vec3.Up, blow.Direction, blow.Position, Vec3.Zero, Vec3.Zero, gameAgent.Velocity, Vec3.Up);
gameAgent.RegisterBlow(blow, attackCollisionDataForDebugPurpose);
}
}
}
protected override void OnInit()
{
base.OnInit();
base.SetScriptComponentToTick(this.GetTickRequirement());
List<GameEntity> entityList = base.GameEntity.GetEntityAndChildren().ToList();
Max_x = entityList.Max(a => a.GlobalPosition.x);
Min_x = entityList.Min(a => a.GlobalPosition.x);
Max_y = entityList.Max(a => a.GlobalPosition.y);
Min_y = entityList.Min(a => a.GlobalPosition.y);
Max_z = entityList.Max(a => a.GlobalPosition.z);
Min_z = entityList.Min(a => a.GlobalPosition.z);
}
public override ScriptComponentBehavior.TickRequirement GetTickRequirement()
{
return ScriptComponentBehavior.TickRequirement.Tick | base.GetTickRequirement();
}
protected override void OnTick(float dt)
{
if (EnabledInGame == true)
{
if(GameNetwork.IsMultiplayer)
{
if(GameNetwork.IsServer)
{
this.CheckIfInDamageZone(dt);
}
}
else
{
this.CheckIfInDamageZone(dt);
}
}
}
protected override void OnEditorTick(float dt)
{
base.OnEditorTick(dt);
}
}
}
C#:
using NetworkMessages.FromServer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TaleWorlds.Core;
using TaleWorlds.Engine;
using TaleWorlds.Library;
using TaleWorlds.MountAndBlade;
namespace MyMods
{
public class CS_Teleport : ScriptComponentBehavior
{
public bool EnabledInGame = false;
public string TeleportTag = "cs_teleport_<Number>";
protected float Max_x = 0.0f;
protected float Min_x = 0.0f;
protected float Max_y = 0.0f;
protected float Min_y = 0.0f;
protected float Max_z = 0.0f;
protected float Min_z = 0.0f;
protected GameEntity TeleportPoint = null;
protected Vec3 TeleportPointVec;
private void CheckIfAgentInTeleport(float dt)
{
Vec3 agentPosition;
foreach (Agent gameAgent in Mission.Current.Agents.ToList())
{
agentPosition = gameAgent.GetChestGlobalPosition();
if (agentPosition.x > Min_x && agentPosition.x < Max_x && agentPosition.y > Min_y && agentPosition.y < Max_y && agentPosition.z > Min_z && agentPosition.z < Max_z)
{
gameAgent.TeleportToPosition(TeleportPointVec);
}
}
}
protected override void OnInit()
{
base.OnInit();
base.SetScriptComponentToTick(this.GetTickRequirement());
List<GameEntity> entityList = base.GameEntity.GetEntityAndChildren().ToList();
Max_x = entityList.Max(a => a.GlobalPosition.x);
Min_x = entityList.Min(a => a.GlobalPosition.x);
Max_y = entityList.Max(a => a.GlobalPosition.y);
Min_y = entityList.Min(a => a.GlobalPosition.y);
Max_z = entityList.Max(a => a.GlobalPosition.z);
Min_z = entityList.Min(a => a.GlobalPosition.z);
TeleportPoint = Mission.Current.Scene.FindEntitiesWithTag(TeleportTag).ToList<GameEntity>().FirstOrDefault();
TeleportPointVec = TeleportPoint.GlobalPosition;
}
public override ScriptComponentBehavior.TickRequirement GetTickRequirement()
{
return ScriptComponentBehavior.TickRequirement.Tick | base.GetTickRequirement();
}
protected override void OnTick(float dt)
{
if (EnabledInGame == true)
{
if (GameNetwork.IsMultiplayer)
{
if (GameNetwork.IsServer)
{
this.CheckIfAgentInTeleport(dt);
}
}
else
{
this.CheckIfAgentInTeleport(dt);
}
}
}
protected override void OnEditorTick(float dt)
{
base.OnEditorTick(dt);
}
}
}
Last edited: