Commit 190745e4 authored by Mikleo's avatar Mikleo

Retain scenario keyvalues, fix buildable selection.

parent dfab6a5b
Pipeline #9235 passed with stages
in 15 seconds
......@@ -9,7 +9,7 @@
#include <updater>
#define PluginVersion "0.95"
#define PluginVersion "0.97"
float pVersion;
// note linearmap field is unstable
......@@ -20,15 +20,9 @@ float pVersion;
char currentScenario[64];
char ScenarioDescription[128];
char ScenarioDetails[256];
char ScenarioAuthor[32];
KeyValues currentScenarioKV;
float ScenarioRefineryMultiplier = -1.0;
float ScenarioPlayerRefineryMultiplier = -1.0;
int ScenarioFreezeTime;
int ScenarioBaseSwap;
int lastMinorEditTime = 0;
......@@ -62,6 +56,8 @@ bool usedFlagIndex[32] = {false,...};
ConVar ef_editlock,ef_baseswap,ef_scenario_vote_delay,ef_scenario_vote_duration,ef_scenario_vote_runoff_duration,ef_scenario_vote_min_timeleft,ef_scenario_vote_display_description,ef_scenario_vote_display_name,ef_scenario_vote_display_tags,ef_scenario_reload_map_config,ef_votelist_base,ef_alledit,ef_downloadeditorcfg,ef_disabletakedamage,ef_useblockmodels;
ConVar emp_sv_commander_freeze_time, emp_sv_player_refinery_multiplier, emp_sv_refinery_multiplier;
bool mapHasBeenEdited = false;
char nextMapScenario[64];
......@@ -198,7 +194,6 @@ public void OnPluginStart()
AddCommandListener(Command_changelevel,"changelevel");
AddCommandListener(Command_Plugin_Version, "ef_version");
ef_disabletakedamage = CreateConVar("ef_disabletakedamage", "1", "disable using SDKHooks_TakeDamage, to deal with offset issues");
ef_editlock = CreateConVar("ef_editlock", "1", "prevent admins from edit map entities/resources/tickets after game has begun.");
ef_baseswap = CreateConVar("ef_baseswap", "0", "Enable Base Swapping");
......@@ -220,6 +215,9 @@ public void OnPluginStart()
ef_downloadeditorcfg = CreateConVar("ef_downloadeditorcfg","0","Add editor.cfg to download list");
idxArmor = FindSendPropInfo("CEmpTank", "m_iEngine") -12;
emp_sv_commander_freeze_time = FindConVar("emp_sv_commander_freeze_time");
emp_sv_player_refinery_multiplier = FindConVar("emp_sv_player_refinery_multiplier");
emp_sv_refinery_multiplier = FindConVar("emp_sv_refinery_multiplier");
......@@ -228,6 +226,8 @@ public void OnPluginStart()
LoadEntData();
Funcs_OnPluginStart();
}
public OnMapEnd()
......@@ -239,6 +239,13 @@ public OnMapEnd()
}
// make sure baseswap is turned off for the next round.
ef_baseswap.IntValue = 0;
delete currentScenarioKV;
Funcs_OnMapEnd();
}
bool CanEditMap(int client)
......@@ -277,19 +284,13 @@ public OnClientConnected(int client)
}
public OnMapStart()
{
currentScenarioKV = new KeyValues("Scenario");
int ef_baseswap_temp = ef_baseswap.IntValue;
AutoExecConfig(true, "empfun");
ef_baseswap.IntValue = ef_baseswap_temp;
strcopy(currentScenario,sizeof(currentScenario)," ");
strcopy(ScenarioAuthor,sizeof(ScenarioAuthor)," ");
strcopy(ScenarioDescription,sizeof(ScenarioDescription)," ");
strcopy(ScenarioDetails,sizeof(ScenarioDetails)," ");
strcopy(lastCommand,sizeof(lastCommand)," ");
ScenarioFreezeTime = -1;
ScenarioRefineryMultiplier = -1.0;
ScenarioPlayerRefineryMultiplier = -1.0;
ScenarioBaseSwap = -1;
mapHasBeenEdited = false;
// even if we don't have baseswap enabled, decide beforehand if we wish to do it for this map.
doBaseSwap = GetRandomInt(0, 9) >= 5;
......@@ -347,8 +348,11 @@ public OnMapStart()
AddFileToDownloadsTable("materials/models/empfun/platform11.vmt");
}
latestKnownMapEntity = 0;
PrecacheSound("weapons/mortar/mortar_explode2.wav");
latestKnownMapEntity = 0;
Funcs_OnMapStart();
}
public OnGameStart()
{
......@@ -2363,7 +2367,7 @@ StartGlowing(int entity)
int r,g,b,a;
GetEntityRenderColor(entity, r, g, b, a);
if(a < 200)
SetEntityRenderColor(entity, 0, 255, 0,a);
SetEntityRenderColor(entity, 11, 255, 11,a);
else if(r==255 && g ==255 && b == 255)
SetEntityRenderColor(entity, 160, 255, 160,a);
}
......@@ -2381,7 +2385,7 @@ StopGlowing(int entity)
int r,g,b,a;
GetEntityRenderColor(entity, r, g, b, a);
if(r==160 && g ==255 && b == 160)
if((r==160 && g ==255 && b == 160) || (r==11 && g ==255 && b == 11) )
SetEntityRenderColor(entity, 255, 255, 255,a);
}
......@@ -3037,7 +3041,7 @@ public int Create_Flag(int client,int args,float position[3], float angles[3])
owner = GetTeamArg(arg);
// if creating a flag with a specific team disable basewap variable for this scenario.
if(owner >= 2)
ScenarioBaseSwap = 0;
currentScenarioKV.SetNum("BaseSwap",0);
}
if(GetCmdArg(3, arg, sizeof(arg)))
{
......@@ -3466,27 +3470,45 @@ ShowScenarioInfo(int client, int time,bool exitButton = false)
{
Panel panel = new Panel();
char buffer[256];
if(currentScenarioKV == null)
{
PrintToChat(client,"No scenario loaded");
return;
}
char displayBuffer[256];
Format(buffer,sizeof(buffer),"Scenario: %s",currentScenario);
panel.SetTitle(buffer);
Format(buffer,sizeof(buffer),"Author: %s",ScenarioAuthor);
currentScenarioKV.GetString("Author",buffer,sizeof(buffer));
Format(buffer,sizeof(buffer),"Author: %s",buffer);
panel.DrawText(buffer);
if(strlen(ScenarioDescription) > 1)
currentScenarioKV.GetString("Description",buffer,sizeof(buffer));
if(strlen(buffer) > 1)
{
DivideString(ScenarioDescription,sizeof(ScenarioDescription),75,2,displayBuffer);
DivideString(buffer,sizeof(buffer),75,2,displayBuffer);
panel.DrawText(displayBuffer);
}
if(strlen(ScenarioDetails) > 1)
currentScenarioKV.GetString("details",buffer,sizeof(buffer));
if(strlen(buffer) > 1)
{
DivideString(ScenarioDetails,sizeof(ScenarioDetails),75,3,displayBuffer);
DivideString(buffer,sizeof(buffer),75,3,displayBuffer);
panel.DrawText(displayBuffer);
}
int ScenarioFreezeTime = currentScenarioKV.GetNum("CommFreezeTime",-1);
if(ScenarioFreezeTime != -1)
{
Format(buffer,sizeof(buffer),"CommFreezeTime: %d",ScenarioFreezeTime);
panel.DrawText(buffer);
}
if(ScenarioPlayerRefineryMultiplier >= 0.0 || ScenarioRefineryMultiplier >= 0.0)
float PlayerRefineryMultiplier = currentScenarioKV.GetFloat("PlayerRefineryMultiplier",-1.0);
float RefineryMultiplier = currentScenarioKV.GetFloat("RefineryMultiplier",-1.0);
if(PlayerRefineryMultiplier >= 0.0 || RefineryMultiplier >= 0.0)
{
Format(buffer,sizeof(buffer),"RM: %f PRM: %f",emp_sv_refinery_multiplier.FloatValue,emp_sv_player_refinery_multiplier.FloatValue);
panel.DrawText(buffer);
......@@ -3527,8 +3549,11 @@ public Action Command_Scenario_Info(int client, int args)
return Plugin_Handled;
}
public Action Command_Scenario_Var(int client, int args)
{
// set description and baseswap "Options: Description Author Baseswap(1/0)"
char arg1 [128];
char arg2 [128];
......@@ -3539,33 +3564,33 @@ public Action Command_Scenario_Var(int client, int args)
}
if(StrEqual(arg1,"Description",false))
{
strcopy(ScenarioDescription,sizeof(ScenarioDescription),arg2);
currentScenarioKV.SetString("Description",arg2);
PrintToChat(client,"Set Description to:%s",arg2);
}
if(StrEqual(arg1,"Details",false))
{
strcopy(ScenarioDetails,sizeof(ScenarioDetails),arg2);
currentScenarioKV.SetString("details",arg2);
PrintToChat(client,"Set Details to:%s",arg2);
}
if(StrEqual(arg1,"BaseSwap",false))
{
ScenarioBaseSwap = StringToInt(arg2);
currentScenarioKV.SetString("BaseSwap",arg2);
PrintToChat(client,"Set BaseSwap to:%s",arg2);
}
if(StrEqual(arg1,"CommFreezeTime",false))
{
ScenarioFreezeTime = StringToInt(arg2);
PrintToChat(client,"Set CommFreezeTime to:%d",ScenarioFreezeTime);
currentScenarioKV.SetString("CommFreezeTime",arg2);
PrintToChat(client,"Set CommFreezeTime to:%d",arg2);
}
if(StrEqual(arg1,"RefineryMultiplier",false))
{
ScenarioRefineryMultiplier = StringToFloat(arg2);
PrintToChat(client,"Set RefineryMultiplier to:%f",ScenarioRefineryMultiplier);
currentScenarioKV.SetString("RefineryMultiplier",arg2);
PrintToChat(client,"Set RefineryMultiplier to:%f",arg2);
}
if(StrEqual(arg1,"PlayerRefineryMultiplier",false))
{
ScenarioPlayerRefineryMultiplier = StringToFloat(arg2);
PrintToChat(client,"Set PlayerRefineryMultiplier to:%f",ScenarioPlayerRefineryMultiplier);
currentScenarioKV.SetString("PlayerRefineryMultiplier",arg2);
PrintToChat(client,"Set PlayerRefineryMultiplier to:%f",arg2);
}
PrintToChat(client,"Remember: You will need to save the scenario for your variables to be saved.");
......@@ -3826,7 +3851,18 @@ SaveScenario(int client,char [] filename,bool saveMetaData = true)
char path[256];
GetScenarioPath(filename,path,sizeof(path));
KeyValues kv = new KeyValues("Scenario");
KeyValues kv;
if(currentScenarioKV)
kv = currentScenarioKV;
else
kv = new KeyValues("Scenario");
if(saveMetaData)
SaveMetaData(kv);
......@@ -3837,17 +3873,18 @@ SaveScenario(int client,char [] filename,bool saveMetaData = true)
if(hLimit == 0)
hLimit = BASEHAMMERID -1;
kv.Rewind();
kv.SetString("Description",ScenarioDescription);
kv.SetString("Details",ScenarioDetails);
GetClientName(client,ScenarioAuthor,sizeof(ScenarioAuthor));
kv.SetString("Author",ScenarioAuthor);
kv.SetNum("BaseSwap",ScenarioBaseSwap);
SaveCvars(kv);
kv.SetFloat("version",pVersion);
// hLimit is used so new entities a mapper adds will not be removed by default.
kv.SetNum("hLimit",hLimit);
ExportKV(kv,path);
kv.Rewind();
kv.DeleteKey("Entities");
kv.DeleteKey("BE_Research");
kv.DeleteKey("NF_Research");
if(!StrEqual(filename,"default",false))
{
char backupPath[255];
......@@ -3856,7 +3893,7 @@ SaveScenario(int client,char [] filename,bool saveMetaData = true)
}
delete kv;
if(client > 0)
{
char clientName[128];
......@@ -3865,25 +3902,20 @@ SaveScenario(int client,char [] filename,bool saveMetaData = true)
}
}
SaveCvars(KeyValues kv)
{
kv.SetNum("CommFreezeTime",ScenarioFreezeTime);
kv.SetFloat("PlayerRefineryMultiplier",ScenarioPlayerRefineryMultiplier);
kv.SetFloat("RefineryMultiplier",ScenarioRefineryMultiplier);
}
LoadCvars(KeyValues kv)
{
ScenarioFreezeTime = kv.GetNum("CommFreezeTime",-1);
int ScenarioFreezeTime = kv.GetNum("CommFreezeTime",-1);
if(ScenarioFreezeTime != -1)
{
emp_sv_commander_freeze_time.IntValue = ScenarioFreezeTime;
}
ScenarioPlayerRefineryMultiplier = kv.GetFloat("PlayerRefineryMultiplier",-1.0);
float ScenarioPlayerRefineryMultiplier = kv.GetFloat("PlayerRefineryMultiplier",-1.0);
if(ScenarioPlayerRefineryMultiplier != -1)
{
emp_sv_player_refinery_multiplier.FloatValue = ScenarioPlayerRefineryMultiplier;
}
ScenarioRefineryMultiplier = kv.GetFloat("RefineryMultiplier",-1.0);
float ScenarioRefineryMultiplier = kv.GetFloat("RefineryMultiplier",-1.0);
if(ScenarioRefineryMultiplier != -1)
{
emp_sv_refinery_multiplier.FloatValue = ScenarioRefineryMultiplier;
......@@ -3897,7 +3929,12 @@ bool LoadScenario(int client,char[] filename)
char path[256];
GetScenarioPath(filename,path,sizeof(path));
bool succeeded = false;
delete currentScenarioKV;
KeyValues kv = new KeyValues("Scenario");
currentScenarioKV = kv;
if(!kv.ImportFromFile(path))
{
if(client > 0)
......@@ -3907,6 +3944,7 @@ bool LoadScenario(int client,char[] filename)
else
{
OnMapEdited();
Funcs_OnLoadScenario();
char cfgName[64];
if(strlen(currentScenario) > 0)
{
......@@ -3926,15 +3964,13 @@ bool LoadScenario(int client,char[] filename)
LoadMetaData(kv);
float version = kv.GetFloat("version");
kv.GetString("Description",ScenarioDescription,sizeof(ScenarioDescription));
kv.GetString("Details",ScenarioDetails,sizeof(ScenarioDetails));
kv.GetString("Author",ScenarioAuthor,sizeof(ScenarioAuthor));
ScenarioBaseSwap = kv.GetNum("BaseSwap",-1);
LoadCvars(kv);
int hLimit = kv.GetNum("hLimit",BASEHAMMERID -1 );
kv.JumpToKey("Entities");
LoadEntities(kv,version,hLimit);
kv.Rewind();
kv.DeleteKey("Entities");
if(client > 0)
......@@ -3946,13 +3982,15 @@ bool LoadScenario(int client,char[] filename)
succeeded = true;
}
if(ef_baseswap.IntValue == 1 && ScenarioBaseSwap != 0 || (ef_baseswap.IntValue == 0 && ScenarioBaseSwap > 0) )
int scenarioBaseSwap = currentScenarioKV.GetNum("BaseSwap",-1);
if(ef_baseswap.IntValue == 1 && scenarioBaseSwap != 0 || (ef_baseswap.IntValue == 0 && scenarioBaseSwap > 0) )
{
DelayedBaseSwap();
}
delete kv;
return succeeded;
}
......@@ -5103,6 +5141,8 @@ LoadMetaData(KeyValues kv)
}
kv.Rewind();
kv.DeleteKey("BE_Research");
kv.DeleteKey("NF_Research");
}
}
......@@ -6434,4 +6474,8 @@ public void LoadEntData()
delete kv;
}
\ No newline at end of file
}
// dont implement just timers
// have a callback function as well
// input function for kill
// onoutput monitors outputs
typedef OnCloseCommand = function void (int commandID,char[] remainder);
// elements wont be removed, just disabled. in place so that ids can be preserved
enum struct CommandTrack {
bool enabled;
int entRef;
Handle timerHandle;
OnCloseCommand closeCommand;
char remainder[256];
char identifier[32];
}
// create a simple scriptable timer system
ArrayList commands;
void Funcs_OnPluginStart()
{
commands = new ArrayList(sizeof(CommandTrack));
}
void Funcs_OnMapStart()
{
}
void Funcs_OnMapEnd()
{
ClearCommands();
}
void Funcs_OnLoadScenario()
{
ClearCommands();
}
void ClearCommands()
{
for(int i = 0;i<commands.Length;i++)
{
ClearCommand(i);
}
commands.Clear();
}
void ClearCommand(int index)
{
CommandTrack commandTrack;
commands.GetArray(index,commandTrack,sizeof(commandTrack));
if(commandTrack.enabled)
{
if(commandTrack.timerHandle != INVALID_HANDLE)
{
KillTimer(commandTrack.timerHandle);
}
Call_StartFunction(null, commandTrack.closeCommand);
Call_PushArray(commandTrack,sizeof(commandTrack));
Call_Finish();
commandTrack.enabled = false;
commands.SetArray(index,commandTrack);
}
}
void OnCloseDefault(int commandID,char[] remainder)
{
}
int CreateCommand(int entity,Handle timer,OnCloseCommand closeCommand,char[] remainder)
{
CommandTrack commandTrack;
commandTrack.enabled = true;
commandTrack.entRef = entity;
commandTrack.timerHandle = timer;
commandTrack.closeCommand = closeCommand;
strcopy(remainder,256,commandTrack.remainder);
int insertIndex = -1;
for(int i = 0;i<commands.Length;i++)
{
CommandTrack track;
commands.GetArray(i,track,sizeof(track));
if(!track.enabled)
{
commands.SetArray(i,commandTrack);
insertIndex = i;
}
}
if(insertIndex == -1)
{
insertIndex = commands.Length;
commands.PushArray(commandTrack,sizeof(commandTrack));
}
return insertIndex;
}
DataPack CreateCommandTimer(float timer,Timer func,int flags,int entity,char[] remainder)
{
// add timer to the list
DataPack dataPack1;
Handle timerHandle = CreateDataTimer(timer, func,dataPack1,flags);
int commandID = CreateCommand(entity,timerHandle,OnCloseDefault,remainder);
WritePackCell(dataPack1,commandID);
return dataPack1;
}
int ReadCommandTimer(DataPack dataPack1,CommandTrack commandTrack)
{
ResetPack(dataPack1);
int commandID = ReadPackCell(dataPack1);
commands.GetArray(commandID,commandTrack,sizeof(commandTrack));
return commandID;
}
RunEntityFunctions(int entity,char[] funcString)
{
int index = StrContains(funcString, "func(");
int index = StrContains(funcString, "{{");
if(index != -1)
{
int startIndex = index + 5;
int findIndex = FindCharInString(funcString[startIndex],')') ;
int findIndex = StrContains(funcString[startIndex],"}}");
if(findIndex != -1)
{
int endIndex = startIndex + findIndex + 1;
int size = endIndex - startIndex;
char command[64];
char command[256];
strcopy(command,size,funcString[startIndex]);
char arg1[64];
BreakApartString(command,sizeof(command), arg1, sizeof(arg1));
if(StrEqual(arg1,"spawnpresetmovementrepeat"))
{
SpawnPresetMovementRepeat(entity,command,sizeof(command));
}
else if(StrEqual(arg1,"destroyafter"))
{
TimedDestroy(entity,command,sizeof(command));
}
RunEntityFunctionInternal(entity,command);
// run the next function
RunEntityFunctions(entity,funcString[findIndex]);
}
}
}
// run the first command and save the next one.
RunEntityFunctionInternal(int entity,char[] funcString)
{
TrimString(funcString);
int findIndex = StrContains(funcString, "->");
if(findIndex == -1)
{
findIndex = strlen(funcString);
}
char command[256];
strcopy(command,findIndex,funcString);
int remainingStart = findIndex + 2;
int remainingLength = strlen(funcString) - remainingStart;
char remainder[256];
strcopy(remainder,remainingLength,funcString[remainingStart]);
char args[256];
BreakApartString(command,sizeof(command), args, sizeof(args));
if(StrEqual(command,"after"))
{
// we need to push the remaining stuff into
AfterCommand(entity,args,remainder);
}
else if(StrEqual(command,"onstart"))
{
// just use a timer to tell if game has started
}
else if(StrEqual(command,"afterstart"))
{
// just translate to onstart -> after
}
else if(StrEqual(command,"every"))
{
// use a repeating timer
}
else if(StrEqual(command,"waittimebelow"))
{
// just use a timer to tell if wait time is below a specific amount
}
else if(StrEqual(command,"spawnpresetmovementrepeat"))
{
SpawnPresetMovementRepeat(entity,command,remainder);
}
else if(StrEqual(command,"input"))
{
// do acceptentity input here
}
else if(StrEqual(command,"onOutput"))
{
// hook output event here.
}
else if(StrEqual(command,"target"))
{
// change target entity (entref) , very useful for switching targets here.
}
else if(StrEqual(command,"spawnpreset"))
{
// spawnpreset here.
}
}
// simpler way to break up string
void BreakApartString(char[] mainString,int mainStringSize,char[] argString,int argStringSize)
{
......@@ -40,15 +234,36 @@ void BreakApartString(char[] mainString,int mainStringSize,char[] argString,int
else
strcopy(mainString,mainStringSize,mainString[index]);
}
TimedDestroy(int entity,char[] args,int argsSize)
public void AfterCommand(int entity,char[] args,char[] remainder)
{
int entRef = EntIndexToEntRef(entity);
// that is the preset name
CreateCommandTimer(1.0,Timer_After,0,entity,remainder);
char arg1[32];
BreakApartString(args,argsSize,arg1,sizeof(arg1));
float timer = StringToFloat(arg1);
}
public Action Timer_After(Handle timer,DataPack dataPack1)
{
// read
CommandTrack commandTrack;
int commandID = ReadCommandTimer(dataPack1,commandTrack);
RunEntityFunctionInternal(commandTrack.entRef,commandTrack.remainder);
// need to do this even if not repeating
ClearCommand(commandID);
}
CreateTimer(timer, Timer_Destroy,entRef);