new levelscriptevent action types

This commit is contained in:
AlessandroCH
2025-05-30 00:32:25 +02:00
parent f416665d40
commit 5ae50be507
14 changed files with 468 additions and 43 deletions

View File

@@ -104,6 +104,7 @@ namespace Campofinale.Game.MissionSys
missions.Add(new GameMission(id, state));
if (notify)
{
ScMissionStateUpdate s = new()
{
MissionId = data.missionId,
@@ -231,6 +232,38 @@ namespace Campofinale.Game.MissionSys
quests.Remove(quest);
}
}
public void TrackMission(string v)
{
curMission = v;
owner.Send(ScMsgId.ScTrackMissionChange, new ScTrackMissionChange()
{
MissionId = curMission,
});
}
public void CompleteMission(string v)
{
if(curMission == v)
{
TrackMission("");
}
GameMission mission = missions.Find(m => m.missionId == v);
MissionDataTable data = ResourceManager.missionDataTable.Find(m => m.missionId == v);
if (mission != null && data != null)
{
mission.state=MissionState.Completed;
ScMissionStateUpdate s = new()
{
MissionId = mission.missionId,
MissionState = (int)mission.state,
SucceedId = -1,
};
owner.Send(ScMsgId.ScMissionStateUpdate, s);
//TODO rewards
}
}
}
public class GameQuest
{

View File

@@ -1,5 +1,6 @@
using Campofinale.Game.Entities;
using Campofinale.Game.Inventory;
using Campofinale.Game.Spawners;
using Campofinale.Packets.Sc;
using Campofinale.Resource;
using MongoDB.Bson.Serialization.Attributes;
@@ -255,6 +256,8 @@ namespace Campofinale.Game
public bool alreadyLoaded = false;
[BsonIgnore, JsonIgnore]
public List<ulong> activeScripts = new();
[BsonIgnore, JsonIgnore]
public List<GameSpawner> gameSpawners = new();
public int GetCollection(string id)
{
if (collections.ContainsKey(id))
@@ -359,6 +362,7 @@ namespace Campofinale.Game
type = en.entityType,
};
entity.defaultHide = en.defaultHide;
entities.Add(entity);
});
GetEntityExcludingChar().ForEach(e =>
@@ -401,6 +405,15 @@ namespace Campofinale.Game
}
public void UpdateShowEntities()
{
for (int i = 0; i < gameSpawners.Count; i++)
{
GameSpawner spawner = gameSpawners[i];
if(spawner != null)
{
spawner.Update(GetOwner());
}
}
List<Entity> toSpawn = new();
foreach(Entity e in GetEntityExcludingChar())
{

View File

@@ -0,0 +1,67 @@
using Campofinale.Game.Entities;
using Campofinale.Resource;
using Campofinale.Resource.Dynamic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Game.Spawners
{
public class GameSpawner
{
public Scene scene;
public int curWave = 1;
public int curGroup = 1;
public string configId;
public bool spawned;
public SpawnerConfig GetConfig()
{
return ResourceManager.spawnerConfigs.Find(s => s.configId == configId);
}
public SpawnerConfig.WaveGroup GetCurrentWaveGroup()
{
return GetConfig().waveMap[$"{curWave}"].groupMap[$"{curGroup}"];
}
public int GetEnemiesOfCurrentWave()
{
return scene.entities.FindAll(e => e.dependencyGroupId == GetCurrentWaveGroup().groupId).Count;
}
public void Update(Player player)
{
if (spawned)
{
if (GetEnemiesOfCurrentWave() < 1)
{
if (GetConfig().waveMap.ContainsKey($"{curWave + 1}"))
{
curWave++;
spawned = false;
}
}
}
else
{
foreach (var item in GetCurrentWaveGroup().actionMap.Values)
{
Logger.Print($"Debug: Spawning {item.libraryKey}");
scene.entities.Add(new EntityMonster(item.libraryKey, 1, player.roleId, item.position, item.rotation, scene.sceneNumId)
{
dependencyGroupId = GetCurrentWaveGroup().groupId,
defaultHide = false,
spawned = false
});
}
spawned = true;
}
}
}
}

View File

@@ -14,16 +14,7 @@ namespace Campofinale.Packets.Cs
session.teams[req.TeamIndex].leader=req.LeaderId;
session.teams[req.TeamIndex].members= req.CharTeam.ToList();
ScCharBagSetTeam team = new()
{
CharTeam = { req.CharTeam },
LeaderId = req.LeaderId,
ScopeName = 1,
TeamIndex = req.TeamIndex,
TeamType = CharBagTeamType.Main,
};
session.Send(ScMsgId.ScCharBagSetTeam,team);
session.Send(new PacketScCharBagSetTeam(session,session.teams[req.TeamIndex], req.TeamIndex));
session.Send(new PacketScSelfSceneInfo(session, Resource.SelfInfoReasonType.SlrChangeTeam));
}

View File

@@ -0,0 +1,22 @@
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Campofinale.Resource;
namespace Campofinale.Packets.Cs
{
public class HandleCsCheckName
{
[Server.Handler(CsMsgId.CsCheckName)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsCheckName req = packet.DecodeBody<CsCheckName>();
session.Send(ScMsgId.ScCheckName, new ScCheckName()
{
Name = req.Name,
Pass=true
},packet.csHead.UpSeqid);
}
}
}

View File

@@ -0,0 +1,22 @@
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Campofinale.Resource;
namespace Campofinale.Packets.Cs
{
public class HandleCsCheckSensitive
{
[Server.Handler(CsMsgId.CsCheckSensitive)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsCheckSensitive req = packet.DecodeBody<CsCheckSensitive>();
session.Send(ScMsgId.ScCheckSensitive, new ScCheckSensitive()
{
});
}
}
}

View File

@@ -3,7 +3,7 @@ using Campofinale.Game.Entities;
using Campofinale.Network;
using Campofinale.Protocol;
using Campofinale.Resource;
using Campofinale.Resource.Table;
using Campofinale.Resource.Json;
using Pastel;
using System.Net.Sockets;
using static Campofinale.Resource.ResourceManager.LevelScene.LevelData;
@@ -38,7 +38,20 @@ namespace Campofinale.Packets.Cs
}
else
{
/* ScSceneLevelScriptStateNotify rsp = new ScSceneLevelScriptStateNotify()
{
SceneNumId = req.SceneNumId,
ScriptId = req.ScriptId,
State = 3
};
if (!session.sceneManager.GetCurScene().activeScripts.Contains(req.ScriptId))
{
session.sceneManager.GetCurScene().activeScripts.Add(req.ScriptId);
session.sceneManager.GetCurScene().UpdateShowEntities();
}
session.Send(ScMsgId.ScSceneLevelScriptStateNotify, rsp);*/
}
@@ -59,20 +72,9 @@ namespace Campofinale.Packets.Cs
State = 4
};
session.Send(ScMsgId.ScSceneLevelScriptStateNotify, rsp, packet.csHead.UpSeqid);
session.Send(ScMsgId.ScSceneLevelScriptStateNotify, rsp);
}
else
{
ScSceneLevelScriptStateNotify rsp = new ScSceneLevelScriptStateNotify()
{
SceneNumId = req.SceneNumId,
ScriptId = req.ScriptId,
State = 4
};
session.Send(ScMsgId.ScSceneLevelScriptStateNotify, rsp, packet.csHead.UpSeqid);
}
}
@@ -107,25 +109,98 @@ namespace Campofinale.Packets.Cs
case ScriptActionType.EnterScene:
player.EnterScene((int)action.valueUlong[0]);
break;
case ScriptActionType.CompleteMission:
player.missionSystem.CompleteMission(action.valueStr[0]);
break;
case ScriptActionType.AddMission:
player.missionSystem.AddMission(action.valueStr[0]);
player.missionSystem.AddMission(action.valueStr[0],MissionState.Processing,true);
if(action.valueUlong.Length > 0)
{
player.missionSystem.TrackMission(action.valueStr[0]);
}
break;
case ScriptActionType.StartSpawner:
player.sceneManager.GetCurScene().gameSpawners.Add(new Game.Spawners.GameSpawner()
{
configId = action.valueStr[0],
scene= player.sceneManager.GetCurScene()
});
break;
case ScriptActionType.AddCharacter:
Character chara =player.AddCharacter(action.valueStr[0],(int) action.valueUlong[0],true);
player.AddToTeam(player.teamIndex, chara.guid);
break;
case ScriptActionType.ChangeScriptPropertyBool:
int i = 0;
ScSceneUpdateLevelScriptProperty update1 = new()
{
SceneNumId = req.SceneNumId,
ScriptId = req.ScriptId,
};
foreach (string keyId in action.valueStr)
{
long val = (long)action.valueUlong[i];
LevelScriptData levelscript = ResourceManager.GetLevelData(player.curSceneNumId).levelData.levelScripts.Find(l => l.scriptId == req.ScriptId);
if (levelscript != null)
{
int key = levelscript.GetPropertyId(keyId, new List<int>());
ParamKeyValue v = new()
{
key = keyId,
value = new ParamKeyValue.ParamValue()
{
type = ParamRealType.Bool,
valueArray = new[]
{
new ParamKeyValue.ParamValueAtom()
{
valueBit64=val,
}
}
}
};
update1.Properties.Add(key, v.ToProto());
}
i++;
}
player.Send(ScMsgId.ScSceneUpdateLevelScriptProperty, update1);
break;
case ScriptActionType.StartScript:
foreach (ulong id in action.valueUlong)
{
ScSceneLevelScriptStateNotify rsp = new ScSceneLevelScriptStateNotify()
{
SceneNumId = req.SceneNumId,
ScriptId = id,
State = 4
};
player.Send(ScMsgId.ScSceneLevelScriptStateNotify, rsp);
}
break;
case ScriptActionType.CallClientEvent:
foreach(string id in action.valueStr)
{
LevelScriptData levelscript = ResourceManager.GetLevelData(player.curSceneNumId).levelData.levelScripts.Find(l => l.actionMap.dataMap.headerList.Any(h=>h._eventKey.constValue==id));
ScSceneTriggerClientLevelScriptEvent trigger = new()
{
EventName = id,
SceneNumId = req.SceneNumId,
ScriptId = req.ScriptId,
ScriptId = levelscript== null ? req.ScriptId : levelscript.scriptId,
};
player.Send(ScMsgId.ScSceneTriggerClientLevelScriptEvent, trigger);
}
break;
case ScriptActionType.CompleteMission:
//player.missionSystem.C(action.valueStr[0]);
break;
default:
Logger.PrintWarn("Script Action not implemented");
break;

View File

@@ -0,0 +1,23 @@
using Campofinale.Network;
using Campofinale.Packets.Sc;
using Campofinale.Protocol;
using Campofinale.Resource;
namespace Campofinale.Packets.Cs
{
public class HandleCsSetName
{
[Server.Handler(CsMsgId.CsSetName)]
public static void Handle(Player session, CsMsgId cmdId, Packet packet)
{
CsSetName req = packet.DecodeBody<CsSetName>();
session.nickname = req.Name;
session.Send(ScMsgId.ScSetName, new ScSetName()
{
Name = req.Name,
},packet.csHead.UpSeqid);
}
}
}

View File

@@ -0,0 +1,24 @@
using Campofinale.Game;
using Campofinale.Network;
using Campofinale.Protocol;
namespace Campofinale.Packets.Sc
{
public class PacketScCharBagSetTeam : Packet
{
public PacketScCharBagSetTeam(Player client, Team team, int index) {
ScCharBagSetTeam proto = new ScCharBagSetTeam()
{
CharTeam = {team.members },
LeaderId = team.leader,
ScopeName = 1,
TeamIndex = index,
TeamType = CharBagTeamType.Main,
};
SetData(ScMsgId.ScCharBagSetTeam, proto);
}
}
}

View File

@@ -16,7 +16,8 @@ namespace Campofinale.Packets.Sc
SummonList =
{
}
},
},
HasExtraObject = entities.Count > 1

View File

@@ -207,18 +207,37 @@ namespace Campofinale
/// Add a character with template id if not present in the chars list *Added in 1.1.6*
/// </summary>
/// <param name="id"></param>
public void AddCharacter(string id, bool notify = false)
public Character AddCharacter(string id, bool notify = false)
{
Character chara = GetCharacter(id);
if (chara == null)
{
Character c = new Character(roleId, id, 1);
chars.Add(c);
chara = new Character(roleId, id, 1);
chars.Add(chara);
if (notify)
{
Send(new PacketScCharBagAddChar(this,c));
Send(new PacketScCharBagAddChar(this,chara));
}
}
return chara;
}
/// <summary>
/// Add a character with template id and level if not present in the chars list *Added in 1.1.6*
/// </summary>
/// <param name="id"></param>
public Character AddCharacter(string id, int level, bool notify = false)
{
Character chara = GetCharacter(id);
if (chara == null)
{
chara = new Character(roleId, id, level);
chars.Add(chara);
if (notify)
{
Send(new PacketScCharBagAddChar(this, chara));
}
}
return chara;
}
/// <summary>
/// Remove a character using template id *Added in 1.1.6*
@@ -691,5 +710,17 @@ namespace Campofinale
UnlockSystemType = (int)t
});
}
public void AddToTeam(int index, ulong guid)
{
if (teams[index].members.Count < 4)
{
teams[index].members.Add(guid);
Send(new PacketScCharBagSetTeam(this, teams[index], index));
if(index==this.teamIndex)
Send(new PacketScSelfSceneInfo(this, Resource.SelfInfoReasonType.SlrChangeTeam));
}
}
}
}

View File

@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using static Campofinale.Resource.ResourceManager;
namespace Campofinale.Resource.Dynamic
{
public class SpawnerConfig
{
public string configId;
public Dictionary<string, SpawnerWave> waveMap = new();
public SpawnerConfig() { }
public class SpawnerWave
{
public int waveId;
public bool repeatable;
public int waveModeKillCount;
public Dictionary<string, WaveGroup> groupMap = new();
}
public class WaveGroup
{
public int groupId;
public int groupMode;
public int groupModeKillCount;
public float timestamp;
public Dictionary<string, GroupAction> actionMap = new();
}
public class GroupAction
{
[JsonPropertyName("$type")]
public string type;
public int actionId;
public float timestamp;
public string libraryKey;
public int spawnCount;
public float spawnInterval;
public Vector3f position;
public Vector3f rotation;
public float randomizeRadius;
public int routeId;
}
}
}

View File

@@ -4,10 +4,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Campofinale.Resource.Table
namespace Campofinale.Resource.Json
{
[TableCfgType("Json/LevelScriptEvents.json", LoadPriority.LOW)]
public class LevelScriptEvent : TableCfgResource
public class LevelScriptEvent
{
public string eventName;
public string comment;
@@ -30,6 +29,10 @@ namespace Campofinale.Resource.Table
AddMission = 6,
CompleteMission = 7,
SpawnEnemyByScriptId = 8,
CallClientEvent = 9
CallClientEvent = 9,
StartScript = 10,
ChangeScriptPropertyBool = 11,
StartSpawner = 12,
AddCharacter = 13
}
}

View File

@@ -1,4 +1,6 @@
using Campofinale.Resource.Table;
using Campofinale.Resource.Dynamic;
using Campofinale.Resource.Json;
using Campofinale.Resource.Table;
using Newtonsoft.Json;
using static Campofinale.Resource.ResourceManager.LevelScene;
@@ -73,7 +75,7 @@ namespace Campofinale.Resource
public static InteractiveTable interactiveTable = new(); //
public static List<LevelScene> levelDatas = new();
public static List<InteractiveData> interactiveData = new();
public static List<SpawnerConfig> spawnerConfigs = new();
public static int GetSceneNumIdFromLevelData(string name)
{
if (levelDatas.Find(a => a.id == name) == null) return 0;
@@ -102,6 +104,7 @@ namespace Campofinale.Resource
public static void Init()
{
Logger.Print("Loading TableCfg resources");
// TODO: move all tables to the folder
sceneAreaTable=JsonConvert.DeserializeObject<Dictionary<string, SceneAreaTable>>(ReadJsonFile("TableCfg/SceneAreaTable.json"));
strIdNumTable = JsonConvert.DeserializeObject<StrIdNumTable>(ReadJsonFile("TableCfg/StrIdNumTable.json"));
characterTable = JsonConvert.DeserializeObject<Dictionary<string, CharacterTable>>(ReadJsonFile("TableCfg/CharacterTable.json"));
@@ -146,6 +149,8 @@ namespace Campofinale.Resource
interactiveTable = JsonConvert.DeserializeObject<InteractiveTable>(ReadJsonFile("Json/Interactive/InteractiveTable.json"));
LoadInteractiveData();
LoadLevelDatas();
LoadScriptsEvent();
LoadSpawners();
ResourceLoader.LoadTableCfg();
if (missingResources)
@@ -233,6 +238,43 @@ namespace Campofinale.Resource
}
}
public static void LoadScriptsEvent()
{
Logger.Print("Loading ScriptsEvents");
string directoryPath = @"Json/ScriptEvents";
string[] jsonFiles = Directory.GetFiles(directoryPath, "*.json", SearchOption.AllDirectories);
foreach (string json in jsonFiles)
{
Dictionary<string,LevelScriptEvent> events = JsonConvert.DeserializeObject<Dictionary<string, LevelScriptEvent>>(ReadJsonFile(json));
foreach(KeyValuePair<string,LevelScriptEvent> e in events)
{
if (levelScriptsEvents.ContainsKey(e.Key))
{
Logger.PrintWarn($"{e.Key} already added, skipping the one in {json}");
}
else
{
levelScriptsEvents.Add(e.Key,e.Value);
}
}
}
Logger.Print($"Loaded {levelScriptsEvents.Count} ScriptsEvents");
}
public static void LoadSpawners()
{
Logger.Print("Loading Spawners");
string directoryPath = @"DynamicAssets\gamedata\spawnerconfig";
string[] jsonFiles = Directory.GetFiles(directoryPath, "*.json", SearchOption.AllDirectories);
foreach (string json in jsonFiles)
{
SpawnerConfig spawner = JsonConvert.DeserializeObject<SpawnerConfig>(ReadJsonFile(json));
spawnerConfigs.Add(spawner);
}
Logger.Print($"Loaded {spawnerConfigs.Count} Spawners");
}
public static void LoadLevelDatas()
{
Logger.Print("Loading LevelData resources");
@@ -512,8 +554,9 @@ namespace Campofinale.Resource
public class LevelScriptData
{
public ulong scriptId;
public List<ParamKeyValue> properties;
public Dictionary<int, string> propertyIdToKeyMap;
public List<ParamKeyValue> properties = new();
public Dictionary<int, string> propertyIdToKeyMap = new();
public ScriptActionMap actionMap = new();
public int GetPropertyId(string key, List<int> toExclude)
@@ -527,6 +570,28 @@ namespace Campofinale.Resource
}
return 0;
}
public class ScriptActionMap
{
public ActionDataMap dataMap = new();
public class ScriptHeader
{
public string _uid = "";
public EventKey _eventKey = new();
public class EventKey
{
public string constValue ="";
}
}
public class ActionDataMap
{
public List<ScriptHeader> headerList = new();
}
}
}
public class LevelFactoryRegionData
{