From 893e0b6359696ddd618eb0d1f5ff288fa720e716 Mon Sep 17 00:00:00 2001 From: higps <59850204+higps@users.noreply.github.com> Date: Thu, 5 Oct 2023 02:05:16 +0200 Subject: [PATCH] working config reader --- berobot_config_reader.sp | 220 ------------------------- berobot_config_reader_psuedo.sp | 145 ++++++++++++++++ config_reader_WIP.sp | 284 ++++++++++++++++++++++++++++++++ include/berobot.inc | 4 + include/berobot_core.inc | 4 + robot_sample.cfg | 89 ++++++++++ robot_sample2.cfg | 89 ++++++++++ 7 files changed, 615 insertions(+), 220 deletions(-) delete mode 100644 berobot_config_reader.sp create mode 100644 berobot_config_reader_psuedo.sp create mode 100644 config_reader_WIP.sp create mode 100644 robot_sample.cfg create mode 100644 robot_sample2.cfg diff --git a/berobot_config_reader.sp b/berobot_config_reader.sp deleted file mode 100644 index 42006f72..00000000 --- a/berobot_config_reader.sp +++ /dev/null @@ -1,220 +0,0 @@ -#pragma semicolon 1 -#include -#include -#include -#include -#include - -#define PLUGIN_VERSION "1.0" -#define ROBOT_NAME "HiGPS" -#define ROBOT_ROLE "Damage" -#define ROBOT_CLASS "Heavy" -#define ROBOT_SUBCLASS "Hitscan" -#define ROBOT_DESCRIPTION "LVL 1 Deflector" -#define ROBOT_TIPS "You have the level 1 deflector upgrade!\nShoot down rockets, grenades, and other projectiles" -#define ROBOT_ON_DEATH "HiGPS has the level 1 deflector perk\nShoot explosives at his feet to make destroying them harder" - -#define ROBOTMODEL "models/bots/heavy_boss/bot_heavy_boss.mdl" -#define SPAWN "#mvm/giant_heavy/giant_heavy_entrance.wav" -#define DEATH "mvm/sentrybuster/mvm_sentrybuster_explode.wav" -#define LOOP "mvm/giant_heavy/giant_heavy_loop.wav" - -#define SOUND_GUNFIRE ")mvm/giant_heavy/giant_heavy_gunfire.wav" -#define SOUND_GUNSPIN ")mvm/giant_heavy/giant_heavy_gunspin.wav" -#define SOUND_WINDUP ")mvm/giant_heavy/giant_heavy_gunwindup.wav" -#define SOUND_WINDDOWN ")mvm/giant_heavy/giant_heavy_gunwinddown.wav" - -float scale = 1.75; - -public Plugin:myinfo = -{ - name = "[TF2] Config Robot Creator", - author = "HiGPS", - description = "Creates robots from a config file", - version = PLUGIN_VERSION, - url = "www.sourcemod.com" -} - -public OnPluginStart() -{ - LoadTranslations("common.phrases"); - - while(robots) - { - RobotDefinition robot; - robot.name = ROBOT_NAME; - robot.role = ROBOT_ROLE; - robot.class = ROBOT_CLASS; - robot.subclass = ROBOT_SUBCLASS; - robot.shortDescription = ROBOT_DESCRIPTION; - robot.sounds.spawn = SPAWN; - robot.sounds.loop = LOOP; - robot.sounds.gunfire = SOUND_GUNFIRE; - robot.sounds.gunspin = SOUND_GUNSPIN; - robot.sounds.windup = SOUND_WINDUP; - robot.sounds.winddown = SOUND_WINDDOWN; - robot.sounds.death = DEATH; - robot.deathtip = ROBOT_ON_DEATH; - robot.weaponsound = ROBOT_WEAPON_SOUND_MINIGUN; - robot.difficulty = ROBOT_DIFFICULTY_EASY; - AddRobot(robot, MakeRobot, PLUGIN_VERSION); - } -} - - -public void OnPluginEnd() -{ - RemoveRobot(ROBOT_NAME); -} - -public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) -{ - return APLRes_Success; -} - -public OnMapStart() -{ - -} - -public Action:SetModel(client, const String:model[]) -{ - if (IsValidClient(client) && IsPlayerAlive(client)) - { - SetVariantString(model); - AcceptEntityInput(client, "SetCustomModel"); - - SetEntProp(client, Prop_Send, "m_bUseClassAnimations", 1); - } -} - -MakeRobot(client) -{ - - TF2_SetPlayerClass(client, TFClass_Heavy); - TF2_RegeneratePlayer(client); - - new ragdoll = GetEntPropEnt(client, Prop_Send, "m_hRagdoll"); - if (ragdoll > MaxClients && IsValidEntity(ragdoll)) AcceptEntityInput(ragdoll, "Kill"); - decl String:weaponname[32]; - GetClientWeapon(client, weaponname, sizeof(weaponname)); - if (strcmp(weaponname, "tf_weapon_", false) == 0) - { - SetEntProp(GetPlayerWeaponSlot(client, 0), Prop_Send, "m_iWeaponState", 0); - TF2_RemoveCondition(client, TFCond_Slowed); - } - - CreateTimer(0.0, Timer_Switch, client); - - SetModel(client, ROBOTMODEL); - - //Hard coded stuff - int iHealth = RobotHealth; - int MaxHealth = ClassHealth; - int iAdditiveHP = iHealth - MaxHealth; - float OverHealRate = 1.5; - - TF2_SetHealth(client, iHealth); - float OverHeal = float(MaxHealth) * OverHealRate; - float TotalHealthOverHeal = iHealth * OverHealRate; - - float OverHealPenaltyRate = OverHeal / TotalHealthOverHeal; - TF2Attrib_SetByName(client, "patient overheal penalty", OverHealPenaltyRate); - - SetEntPropFloat(client, Prop_Send, "m_flModelScale", scale); - SetEntProp(client, Prop_Send, "m_bIsMiniBoss", _:true); - float HealthPackPickUpRate = float(MaxHealth) / float(iHealth); - TF2Attrib_SetByName(client, "health from packs decreased", HealthPackPickUpRate); - -//Variable stuff - - while(Variables) - { - TF2Attrib_SetByName(client, attribute, value); - } - TF2Attrib_SetByName(client, "move speed penalty", 0.5); - TF2Attrib_SetByName(client, "damage force reduction", 0.1); - TF2Attrib_SetByName(client, "airblast vulnerability multiplier", 0.0); - - - TF2Attrib_SetByName(client, "aiming movespeed increased", 2.0); - TF2Attrib_SetByName(client, "max health additive bonus", float(iAdditiveHP)); - TF2Attrib_SetByName(client, "ammo regen", 100.0); - TF2Attrib_SetByName(client, "cancel falling damage", 1.0); - TF2Attrib_SetByName(client, "rage giving scale", 0.85); - - UpdatePlayerHitbox(client, scale); - - TF2_RemoveCondition(client, TFCond_CritOnFirstBlood); - TF2_AddCondition(client, TFCond_SpeedBuffAlly, 0.1); - - PrintHintText(client , ROBOT_TIPS); - -} - -stock TF2_SetHealth(client, NewHealth) -{ - SetEntProp(client, Prop_Send, "m_iHealth", NewHealth, 1); - SetEntProp(client, Prop_Data, "m_iHealth", NewHealth, 1); - SetEntProp(client, Prop_Data, "m_iMaxHealth", NewHealth, 1); -} - -public Action:Timer_Switch(Handle:timer, any:client) -{ - if (IsValidClient(client)) - GiveEquipment(client); -} - -stock GiveEquipment(client) -{ - if (IsValidClient(client)) - { - //Remove items and hats - RoboRemoveAllWearables(client); - //TF2_RemoveAllWearables(client); - TF2_RemoveWeaponSlot(client, 0); - TF2_RemoveWeaponSlot(client, 1); - TF2_RemoveWeaponSlot(client, 2); - - //Cosmetic code - TFTeam iTeam = view_as(GetEntProp(client, Prop_Send, "m_iTeamNum")); - float TeamPaint = 0.0; - - if (iTeam == TFTeam_Blue){ - TeamPaint = TeamPaintBlue; - - } - if (iTeam == TFTeam_Red){ - - TeamPaint = TeamPaintRed; - } - - while(Hats) - { - CreateRoboHat(client, ROTATIONSENSATION, HatLevel, HatQuality, HatPaint, HatScale, HatStyle);//Rotation sensation - - } - - while(Weapons) - { - - - CreateRoboWeapon(client, "tf_weapon_minigun", 850, 6, 1, 0, 0); - - - int Weapon1 = GetPlayerWeaponSlot(client, TFWeaponSlot_Primary); - if(IsValidEntity(Weapon1)) - { - if(b_removeattrib)TF2Attrib_RemoveAll(Weapon1); - - for(attributes) - { - StringAttribute = "Read From Somewhere"; - AttributeValue = ReadFromSomewhere - TF2Attrib_SetByName(Weapon1, StringAttribute, AttributeValue); - } - } - - } - } -} diff --git a/berobot_config_reader_psuedo.sp b/berobot_config_reader_psuedo.sp new file mode 100644 index 00000000..5268a7cd --- /dev/null +++ b/berobot_config_reader_psuedo.sp @@ -0,0 +1,145 @@ +public OnPluginStart() +{ + LoadTranslations("common.phrases"); + + //Please modify the code to load the robot.cfg file and map the values accordingly + while(robots) + { + RobotDefinition robot; + robot.name = ROBOT_NAME; + robot.role = ROBOT_ROLE; + robot.class = ROBOT_CLASS; + robot.subclass = ROBOT_SUBCLASS; + robot.shortDescription = ROBOT_DESCRIPTION; + robot.sounds.spawn = SPAWN; + robot.sounds.loop = LOOP; + robot.sounds.gunfire = SOUND_GUNFIRE; + robot.sounds.gunspin = SOUND_GUNSPIN; + robot.sounds.windup = SOUND_WINDUP; + robot.sounds.winddown = SOUND_WINDDOWN; + robot.sounds.death = DEATH; + robot.deathtip = ROBOT_ON_DEATH; + robot.weaponsound = ROBOT_WEAPON_SOUND_MINIGUN; + robot.difficulty = ROBOT_DIFFICULTY_EASY; + AddRobot(robot, MakeRobot, PLUGIN_VERSION); + } +} + + +public Action:SetModel(client, const String:model[]) +{ + if (IsValidClient(client) && IsPlayerAlive(client)) + { + SetVariantString(model); + AcceptEntityInput(client, "SetCustomModel"); + + SetEntProp(client, Prop_Send, "m_bUseClassAnimations", 1); + } +} + +MakeRobot(client) +{ + + //Below the TFClass_Heavy should be replaced with the TFCLass read from the file, users will write Medic, but the TF2 Setplayer class requires it to be TFClass_Medic, so you will need to add that here + TF2_SetPlayerClass(client, TFClass_Heavy); + + + //Robot initiation stuff, no need to alter this + TF2_RegeneratePlayer(client); + new ragdoll = GetEntPropEnt(client, Prop_Send, "m_hRagdoll"); + if (ragdoll > MaxClients && IsValidEntity(ragdoll)) AcceptEntityInput(ragdoll, "Kill"); + decl String:weaponname[32]; + GetClientWeapon(client, weaponname, sizeof(weaponname)); + if (strcmp(weaponname, "tf_weapon_", false) == 0) + { + SetEntProp(GetPlayerWeaponSlot(client, 0), Prop_Send, "m_iWeaponState", 0); + TF2_RemoveCondition(client, TFCond_Slowed); + } + + CreateTimer(0.0, Timer_Switch, client); + + //Set the robot model string from the config file + SetModel(client, ROBOTMODEL); + + //Use the correct TFClass name and set the health from the config file + RoboSetHealth(client,TFClass_Scout, Health, 1.5); + + + + SetEntPropFloat(client, Prop_Send, "m_flModelScale", scale); + SetEntProp(client, Prop_Send, "m_bIsMiniBoss", _:true); + + + //Add the player attributes from the config file here + while(Variables) + { + TF2Attrib_SetByName(client, attribute, value); + } + TF2Attrib_SetByName(client, "move speed penalty", 0.5); + TF2Attrib_SetByName(client, "damage force reduction", 0.1); + TF2Attrib_SetByName(client, "airblast vulnerability multiplier", 0.0); + + + UpdatePlayerHitbox(client, scale); + + + //Initiation stuff, ignore + TF2_RemoveCondition(client, TFCond_CritOnFirstBlood); + TF2_AddCondition(client, TFCond_SpeedBuffAlly, 0.1); + + //Map the tips from the tips in the config file + PrintHintText(client , ROBOT_TIPS); + +} + + +public Action:Timer_Switch(Handle:timer, any:client) +{ + if (IsValidClient(client)) + GiveEquipment(client); +} + +stock GiveEquipment(client) +{ + if (IsValidClient(client)) + { + //Removes all pre existing items and hats don't touch + RoboRemoveAllWearables(client); + //TF2_RemoveAllWearables(client); + TF2_RemoveWeaponSlot(client, 0); + TF2_RemoveWeaponSlot(client, 1); + TF2_RemoveWeaponSlot(client, 2); + + //Add the code to add the hats from the config file, you will ignore the name and use the itemindex instead + while(Hats) + { + CreateRoboHat(client, ROTATIONSENSATION, HatLevel, HatQuality, HatPaint, HatScale, HatStyle);//Rotation sensation + + } + + + //Add the code to create the weapons, then add the attributes to them + while(Weapons) + { + + CreateRoboWeapon(int client, char[] classname, int itemindex, int quality, int level, int slot, int paint); + + + int Weapon1 = GetPlayerWeaponSlot(client, WEAPON_SLOT); + if(IsValidEntity(Weapon1)) + { + //The b_removeattrib checks if it should remove attributes from the variable "remove_attributes" from the config file + if(b_removeattrib)TF2Attrib_RemoveAll(Weapon1); + + //Modify the code below to add the attributes ot the weapon + for(attributes) + { + StringAttribute = "Read From Somewhere"; + AttributeValue = ReadFromSomewhere + TF2Attrib_SetByName(Weapon1, StringAttribute, AttributeValue); + } + } + + } + } +} diff --git a/config_reader_WIP.sp b/config_reader_WIP.sp new file mode 100644 index 00000000..11b014d8 --- /dev/null +++ b/config_reader_WIP.sp @@ -0,0 +1,284 @@ +#include +#include +#include +#define PATH "cfg/robots" +#define PLUGIN_VERSION "0.01" +KeyValues g_hConfig; +public void OnPluginStart() +{ + char fileName[256]; + Handle dir = OpenDirectory(PATH); + if(dir == null) + { + LogError("Failed to open directory: %s", PATH); + return; + } + + while (ReadDirEntry(dir, fileName, sizeof(fileName))) + { + // Only process .cfg files + if(StrContains(fileName, ".cfg") != -1) + { + // ProcessCfgFile(fileName); + LoadConfig(fileName); + } + } + + CloseHandle(dir); +} + +public void LoadConfig(char[] fileName) +{ + if (g_hConfig != INVALID_HANDLE)delete g_hConfig; + + g_hConfig = new KeyValues("Robot"); + char fullPath[256]; + Format(fullPath, sizeof(fullPath), "%s/%s", PATH, fileName); + PrintToChatAll("Filename %s, fullPath% %s", fileName, fullPath); + g_hConfig.ImportFromFile(fullPath); + ReadConfig(); + + + +} + +public void ReadConfig() +{ + + char robotName[64]; + if (g_hConfig.GetString("name", robotName, sizeof(robotName))) + { + PrintToChatAll("Robot Name: %s", robotName); + + char role[64], class[9], subclass[32], shortDescription[NAMELENGTH], tips[256]; + char deathtip[256], model[256]; + int difficulty, health; + float scale; + RobotDefinition robot; + // Attempt to fetch each attribute and set it + g_hConfig.GetString("role", role, sizeof(role)); + g_hConfig.GetString("class", class, sizeof(class)); + g_hConfig.GetString("subclass", subclass, sizeof(subclass)); + g_hConfig.GetString("shortdescription", shortDescription, sizeof(shortDescription)); + g_hConfig.GetString("tips", tips, sizeof(tips)); + g_hConfig.GetString("deathtip", deathtip, sizeof(deathtip)); + g_hConfig.GetString("model", model, sizeof(model)); + g_hConfig.GetNum("difficulty", difficulty); + g_hConfig.GetNum("health", health); + g_hConfig.GetFloat("scale", scale); + + // Map the attributes to robot's properties + robot.name = robotName; + robot.role = role; + robot.class = class; + robot.subclass = subclass; + robot.shortDescription = shortDescription; + robot.tips = tips; + robot.deathtip = deathtip; + robot.model = model; + robot.difficulty = difficulty; + robot.health = health; + robot.scale = scale; + + AddRobot(robot, MakeGDeflectorH, PLUGIN_VERSION); + } + else + { + PrintToChatAll("Unable to retrieve 'name' from 'Robot'"); + } + + +} + +public void DumpKeys(KeyValues kv, int depth) +{ + char buffer[256]; + char key[64], value[64]; + depth = 0; + + while (true) + { + kv.GetSectionName(key, sizeof(key)); + kv.GetString(NULL_STRING, value, sizeof(value)); + + for (int i = 0; i < depth; i++) // Add some indentation for depth + { + buffer[i] = ' '; + } + Format(buffer[depth], sizeof(buffer) - depth, "%s : %s", key, value); + PrintToChatAll("%s", buffer); + + if (kv.GotoFirstSubKey()) + { + DumpKeys(kv, depth + 2); + kv.GoBack(); + } + + if (!kv.GotoNextKey()) + break; + } +} +// public void ReadConfig() +// { + +// // if (g_hConfig.JumpToKey("Robot", false)) +// // { +// // char robotName[64]; +// // if(g_hConfig.GetString("name", robotName, sizeof(robotName))) +// // { +// // PrintToChatAll("Robot Name: %s", robotName); +// // } +// // else +// // { +// // PrintToChatAll("Unable to retrieve 'name' from 'Robot'"); +// // } + +// // g_hConfig.GoBack(); +// // } +// // else +// // { +// // PrintToChatAll("'Robot' Key does not exist."); +// // } + +// // if (g_hConfig.JumpToKey("Robot", false)) +// // { +// // char robotName[64]; +// // g_hConfig.GetString("name", robotName, sizeof(robotName)); + +// // PrintToChatAll("Robot Name: %s", robotName); + +// // // ApplyChanges(client, entity, g_hConfig, sClass); // Uncomment if needed +// // g_hConfig.GoBack(); +// // } + +// // if (g_hConfig.JumpToKey("Robot", false)) +// // { +// // char robotName[64]; +// // g_hConfig.GetString("name", robotName, sizeof(robotName)); + +// // PrintToChatAll("Robot Name: %s", robotName); + +// // // ApplyChanges(client, entity, g_hConfig, sClass); // Uncomment if needed +// // g_hConfig.GoBack(); +// // } +// } + +// public void ProcessCfgFile(const char[] fileName) +// { +// char fullPath[256]; +// char line[1024]; +// Format(fullPath, sizeof(fullPath), "%s/%s", PATH, fileName); + +// Handle file = OpenFile(fullPath, "r"); +// if(!file) +// { +// LogError("Failed to open file: %s", fullPath); +// return; +// } + +// ArrayList linesList = new ArrayList(); + +// while(ReadFileLine(file, line, sizeof(line))) +// { +// // For now, we just print the lines, but you can process them however you need. +// // LogMessage("File: %s, Line: %s", fileName, line); +// linesList.PushString(line); + +// } +// CloseHandle(file); +// // ParseRobotConfig(linesList); + +// delete linesList; +// } + +// public void ParseRobotConfig(ArrayList linesList) +// { +// RobotDefinition robot +// bool isFirstLine = true; +// for (int i = 0; i < linesList.Length; i++) +// { +// char line[2048]; +// linesList.GetString(i, line, sizeof(line)); + +// char key[64]; +// char value[256]; +// ExtractKeyAndValue(line, key, sizeof(key), value, sizeof(value)); +// // PrintToChatAll("Key is %s value is %s",key, value); +// if(isFirstLine) +// { +// strcopy(robot.name, sizeof(robot.name), key); + +// isFirstLine = false; +// continue; +// } + +// if (StrEqual(key, "role")) +// strcopy(robot.role, sizeof(robot.role), value); +// else if (StrEqual(key, "class")) +// strcopy(robot.class, sizeof(robot.class), value); +// else if (StrEqual(key, "subclass")) +// strcopy(robot.subclass, sizeof(robot.subclass), value); +// else if (StrEqual(key, "description")) +// strcopy(robot.shortDescription, sizeof(robot.shortDescription), value); +// else if (StrEqual(key, "tips")) +// strcopy(robot.tips, sizeof(robot.tips), value); +// else if (StrEqual(key, "on_death")) +// strcopy(robot.deathtip, sizeof(robot.deathtip), value); +// else if (StrEqual(key, "model")) +// strcopy(robot.model, sizeof(robot.model), value); +// else if (StrEqual(key, "difficulty")) +// robot.difficulty = StringToInt(value); +// else if (StrEqual(key, "health")) +// robot.health = StringToInt(value); +// else if (StrEqual(key, "scale")) +// robot.scale = StringToFloat(value); + + +// AddRobot(robot, MakeGDeflectorH, PLUGIN_VERSION); +// } +// } + +// public void ExtractKeyAndValue(const char[] line, char[] key, int keySize, char[] value, int valueSize) +// { +// int equalsPos = StrContains(line, "\" \""); +// if (equalsPos == -1) +// { +// PrintToChatAll("Invalid line format: %s", line); +// // LogError("Invalid line format: %s", line); +// return; +// } + +// int lineLen = strlen(line); + +// // Extract the key +// for (int i = 0; i < equalsPos && i < keySize - 1; i++) +// { +// key[i] = line[i]; +// } +// key[equalsPos] = '\0'; + +// // Extract the value +// int valueStart = equalsPos + 3; // Skip past " \"" +// int valueEnd = lineLen - 1; // Exclude the trailing " character +// int valueLength = valueEnd - valueStart + 1; + +// if (valueLength < 0 || valueLength >= valueSize) +// { +// LogError("Value too long or invalid format in line: %s", line); +// return; +// } + +// for (int i = 0; i < valueLength; i++) +// { +// value[i] = line[valueStart + i]; +// } +// value[valueLength] = '\0'; + +// TrimString(key); +// TrimString(value); +// } + +MakeGDeflectorH(client) +{ + PrintToChatAll("Robot stuff goes here"); +} \ No newline at end of file diff --git a/include/berobot.inc b/include/berobot.inc index e056cee9..c1a5a712 100644 --- a/include/berobot.inc +++ b/include/berobot.inc @@ -99,7 +99,11 @@ enum struct RobotDefinition { char subclass[32]; char shortDescription[NAMELENGTH]; char deathtip[512]; + char tips[512]; + char model[512]; RobotSounds sounds; + int health; + float scale; char deatheffect[64]; int weaponsound; int footstep; diff --git a/include/berobot_core.inc b/include/berobot_core.inc index 88fcfc5d..ba987d44 100644 --- a/include/berobot_core.inc +++ b/include/berobot_core.inc @@ -615,8 +615,12 @@ enum struct Robot { char subclass[32]; char shortDescription[NAMELENGTH]; char deathtip[512]; + char tips[512]; + char model[512]; PrivateForward callback; RobotSounds sounds; + int health; + float scale; Restrictions restrictions; int robotCoinsOnDeath; int teamCoinsOnDeath; diff --git a/robot_sample.cfg b/robot_sample.cfg new file mode 100644 index 00000000..50da9151 --- /dev/null +++ b/robot_sample.cfg @@ -0,0 +1,89 @@ +"HiGPS" +{ + "role" "Damage" + "class" "Heavy" + "subclass" "Hitscan" + "description" "LVL 1 Deflector" + "tips" "You have the level 1 deflector upgrade!\nShoot down rockets, grenades, and other projectiles" + "on_death" "HiGPS has the level 1 deflector perk\nShoot explosives at his feet to make destroying them harder" + "model" "models/bots/heavy_boss/bot_heavy_boss.mdl" + "difficulty" "0" + "health" "5000" + "scale" "1.75" + "sounds" + { + "spawn" "#mvm/giant_heavy/giant_heavy_entrance.wav" + "death" "mvm/sentrybuster/mvm_sentrybuster_explode.wav" + "loop" "mvm/giant_heavy/giant_heavy_loop.wav" + "gunfire" ")mvm/giant_heavy/giant_heavy_gunfire.wav" + "gunspin" ")mvm/giant_heavy/giant_heavy_gunspin.wav" + "windup" ")mvm/giant_heavy/giant_heavy_gunwindup.wav" + "winddown" ")mvm/giant_heavy/giant_heavy_gunwinddown.wav" + } + "player_attributes" + { + "move speed penalty" "0.5" + "damage force reduction" "0.1" + "airblast vulnerability multiplier" "0.0" + "aiming movespeed increased" "2.0" + "ammo regen" "100.0" + "cancel falling damage" "1.0" + "rage giving scale" "0.85" + } + + "weapons" + { + "tf_weapon_minigun" + { + "itemindex" "850" + "quality" "6" + "level" "1" + "slot" "TFWeaponSlot_Primary" + "paint" "0" + "remove_attributes" "1" + "attributes" + { + "attack projectiles" "1.0" + "maxammo primary increased" "2.5" + "killstreak tier" "1.0" + "dmg penalty vs buildings" "0.5" + } + } + // Additional weapons can be added following the same format + } + + "hats" + { + "ROTATIONSENSATION" + { + "itemindex" "30623" + "level" "6" + "quality" "6" + "paint" "TeamPaint" + "scale" "0.75" + "style" "-1.0" + } + "SUMMERSHADES" + { + "itemindex" "486" + "level" "6" + "quality" "6" + "paint" "1315860.0" + "scale" "0.75" + "style" "-1.0" + } + "WEIGHTROOMWARMER" + { + "itemindex" "30178" + "level" "6" + "quality" "6" + "paint" "0.0" + "scale" "1.0" + "style" "-1.0" + } + } + +} + + + diff --git a/robot_sample2.cfg b/robot_sample2.cfg new file mode 100644 index 00000000..10dd2579 --- /dev/null +++ b/robot_sample2.cfg @@ -0,0 +1,89 @@ +"Agro" +{ + "role" "Damage" + "class" "Pyro" + "subclass" "Flames" + "description" "LVL 1 Deflector" + "tips" "You have the level 1 deflector upgrade!\nShoot down rockets, grenades, and other projectiles" + "on_death" "HiGPS has the level 1 deflector perk\nShoot explosives at his feet to make destroying them harder" + "model" "models/bots/heavy_boss/bot_heavy_boss.mdl" + "difficulty" "0" + "health" "5000" + "scale" "1.75" + "sounds" + { + "spawn" "#mvm/giant_heavy/giant_heavy_entrance.wav" + "death" "mvm/sentrybuster/mvm_sentrybuster_explode.wav" + "loop" "mvm/giant_heavy/giant_heavy_loop.wav" + "gunfire" ")mvm/giant_heavy/giant_heavy_gunfire.wav" + "gunspin" ")mvm/giant_heavy/giant_heavy_gunspin.wav" + "windup" ")mvm/giant_heavy/giant_heavy_gunwindup.wav" + "winddown" ")mvm/giant_heavy/giant_heavy_gunwinddown.wav" + } + "player_attributes" + { + "move speed penalty" "0.5" + "damage force reduction" "0.1" + "airblast vulnerability multiplier" "0.0" + "aiming movespeed increased" "2.0" + "ammo regen" "100.0" + "cancel falling damage" "1.0" + "rage giving scale" "0.85" + } + + "weapons" + { + "tf_weapon_minigun" + { + "itemindex" "850" + "quality" "6" + "level" "1" + "slot" "TFWeaponSlot_Primary" + "paint" "0" + "remove_attributes" "1" + "attributes" + { + "attack projectiles" "1.0" + "maxammo primary increased" "2.5" + "killstreak tier" "1.0" + "dmg penalty vs buildings" "0.5" + } + } + // Additional weapons can be added following the same format + } + + "hats" + { + "ROTATIONSENSATION" + { + "itemindex" "30623" + "level" "6" + "quality" "6" + "paint" "TeamPaint" + "scale" "0.75" + "style" "-1.0" + } + "SUMMERSHADES" + { + "itemindex" "486" + "level" "6" + "quality" "6" + "paint" "1315860.0" + "scale" "0.75" + "style" "-1.0" + } + "WEIGHTROOMWARMER" + { + "itemindex" "30178" + "level" "6" + "quality" "6" + "paint" "0.0" + "scale" "1.0" + "style" "-1.0" + } + } + +} + + +