Added command for modifying or scaling class attributes. Minior fixes, see details.

Fixed error getting default classes on early player connect (bots, source tv, etc.).
Fixed jump boost not resetting height velocity. Changed to add to velocity. Jump from boost platform still doesn't work because the velocity is set too early.
Added check for reserved class names when validating.
Updated class default attributes and jump limits.
This commit is contained in:
richard
2009-05-10 18:49:47 +02:00
parent 969aa19b85
commit 4117519b39
9 changed files with 793 additions and 121 deletions

View File

@@ -97,3 +97,499 @@ public Action:Command_ClassDump(client, argc)
return Plugin_Handled;
}
/**
* Modifies class data on one or more classes.
*
* Syntax: zr_class_modify <class> <attribute> <value> [is_multiplier]
*
* class: The class to modify. Can be any class name, or one of the
* following team names; "all", "humans", "zombies" or
* "admins".
* attribute: The name of the class attribute.
* value: Value to set. Use quotes if value is a string.
* is_multiplier: Optional. specifies wether the original value should be
* multiplied by the specified value. Defaults to false.
*
* Note: Original values are retrieved from the original class cache, not the
* modified class cache.
*/
public Action:Command_ClassModify(client, argc)
{
decl String:syntax[1024];
syntax[0] = 0;
if (argc < 3)
{
// Write syntax info.
StrCat(syntax, sizeof(syntax), "Modifies class data on one or more classes. Usage: zr_class_modify <class> <attribute> <value> [is_multiplier]\n\n");
StrCat(syntax, sizeof(syntax), "class: The class to modify. Can be any class name, or one of the following team names; all, humans, zombies or admins.\n");
StrCat(syntax, sizeof(syntax), "attribute: The name of the class attribute.\n");
StrCat(syntax, sizeof(syntax), "value: Value to set. Use quotes if value is a string.\n");
StrCat(syntax, sizeof(syntax), "is_multiplier: Optional. specifies wether the original value should be multiplied by the specified value. Not all attributes support multiplying. Defaults to false.\n\n");
StrCat(syntax, sizeof(syntax), "Note: Original values are retrieved from the original class cache, not the modified class cache.");
ReplyToCommand(client, syntax);
return Plugin_Handled;
}
decl String:classname[64];
decl String:attributename[128];
decl String:value[256];
decl String:ismultiplier[4];
new attributeflag;
new ClassDataTypes:attributetype;
new bool:isgroup;
new bool:hasmultiplier;
new Handle:classlist;
new classindex;
new bool:listresult;
classlist = CreateArray();
// Get command arguments.
GetCmdArg(1, classname, sizeof(classname));
GetCmdArg(2, attributename, sizeof(attributename));
GetCmdArg(3, value, sizeof(value));
// Get last command argument if specified.
if (argc == 4)
{
GetCmdArg(4, ismultiplier, sizeof(ismultiplier));
if (StringToInt(ismultiplier))
{
hasmultiplier = true;
}
}
// Get attribute flag.
attributeflag = ClassAttributeNameToFlag(attributename);
// Validate attribute flag.
if (attributeflag < 0)
{
ReplyToCommand(client, "Invalid class attribute specified.");
return Plugin_Handled;
}
// Get attribute data type.
attributetype = ClassGetAttributeType(attributeflag);
// Check if classname is a group. Add classes to the class list
// and use the specified team filter.
if (StrEqual(classname, "all", false))
{
listresult = ClassAddToArray(classlist);
isgroup = true;
}
else if (StrEqual(classname, "humans", false))
{
listresult = ClassAddToArray(classlist, ZR_CLASS_TEAM_HUMANS);
isgroup = true;
}
else if (StrEqual(classname, "zombies", false))
{
listresult = ClassAddToArray(classlist, ZR_CLASS_TEAM_ZOMBIES);
isgroup = true;
}
else if (StrEqual(classname, "admins", false))
{
listresult = ClassAddToArray(classlist, ZR_CLASS_TEAM_ADMINS);
isgroup = true;
}
// Check if classname is a group.
if (isgroup)
{
// Check if the list is valid.
if (!listresult)
{
ReplyToCommand(client, "Failed to get classes in the specified team: \"%s\".", classname);
return Plugin_Handled;
}
// Loop through all classes in the list.
new listsize = GetArraySize(classlist);
for (new i = 0; i < listsize; i++)
{
classindex = GetArrayCell(classlist, i);
switch (attributetype)
{
case ClassDataType_Boolean:
{
if (!ClassModifyBoolean(classindex, attributeflag, bool:StringToInt(value)))
{
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
}
}
case ClassDataType_Integer:
{
if (hasmultiplier)
{
if (!ClassModifyInteger(classindex, attributeflag, StringToInt(value), StringToFloat(value)))
{
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
}
}
else
{
if (!ClassModifyInteger(classindex, attributeflag, StringToInt(value)))
{
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
}
}
}
case ClassDataType_Float:
{
if (!ClassModifyFloat(classindex, attributeflag, StringToFloat(value), hasmultiplier))
{
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
}
}
case ClassDataType_String:
{
if (!ClassModifyString(classindex, attributeflag, value))
{
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
}
}
}
}
}
else
{
// It's a single class.
classindex = ClassGetIndex(classname);
// Validate classindex.
if (!ClassValidateIndex(classindex))
{
ReplyToCommand(client, "Invalid class name specified.");
return Plugin_Handled;
}
switch (attributetype)
{
case ClassDataType_Boolean:
{
if (!ClassModifyBoolean(classindex, attributeflag, bool:StringToInt(value)))
{
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
}
}
case ClassDataType_Integer:
{
if (hasmultiplier)
{
if (!ClassModifyInteger(classindex, attributeflag, StringToInt(value), StringToFloat(value)))
{
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
}
}
else
{
if (!ClassModifyInteger(classindex, attributeflag, StringToInt(value)))
{
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
}
}
}
case ClassDataType_Float:
{
if (!ClassModifyFloat(classindex, attributeflag, StringToFloat(value)), hasmultiplier)
{
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
}
}
case ClassDataType_String:
{
if (!ClassModifyString(classindex, attributeflag, value))
{
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
}
}
}
}
return Plugin_Handled;
}
/**
* Modify class boolean attribute on a class.
*
* @param classindex The class index.
* @param attributeflag Attribute to modify (a single attribute flag).
* @param value New value to set.
* @return True on success, false otherwise.
*/
bool:ClassModifyBoolean(classindex, attributeflag, bool:value)
{
// Validate class index.
if (!ClassValidateIndex(classindex))
{
return false;
}
switch (attributeflag)
{
case ZR_CLASS_FLAG_ENABLED:
{
ClassDataCache[classindex][class_enabled] = bool:value;
return true;
}
case ZR_CLASS_FLAG_NVGS:
{
ClassDataCache[classindex][class_nvgs] = bool:value;
return true;
}
case ZR_CLASS_FLAG_NO_FALL_DAMAGE:
{
ClassDataCache[classindex][class_no_fall_damage] = bool:value;
return true;
}
}
// Invalid flag or multiple flags combined.
return false;
}
/**
* Modify class integer attribute on a class.
*
* @param classindex The class index.
* @param attributeflag Attribute to modify (a single attribute flag).
* @param value New value to set, or multiply with.
* @param multiplier Optional. Use a multiplier instead of the value,
* that multiplies with the original class value.
* Not all attributes support multipliers. 0.0 to
* disable. Value is ignored if this is non-zero.
* @return True on success, false otherwise.
*/
ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0.0)
{
// Validate class index.
if (!ClassValidateIndex(classindex))
{
return false;
}
// Check if multiplier is specified.
new bool:ismultiplier = (multiplier != 0.0) ? true : false;
switch (attributeflag)
{
case ZR_CLASS_FLAG_ALPHA_INITIAL:
{
if (ismultiplier)
{
value = RoundToNearest(float(ClassData[classindex][class_alpha_initial]) * multiplier);
}
ClassDataCache[classindex][class_alpha_initial] = value;
return true;
}
case ZR_CLASS_FLAG_ALPHA_DAMAGED:
{
if (ismultiplier)
{
value = RoundToNearest(float(ClassData[classindex][class_alpha_damaged]) * multiplier);
}
ClassDataCache[classindex][class_alpha_damaged] = value;
return true;
}
case ZR_CLASS_FLAG_ALPHA_DAMAGE:
{
if (ismultiplier)
{
value = RoundToNearest(float(ClassData[classindex][class_alpha_damage]) * multiplier);
}
ClassDataCache[classindex][class_alpha_damage] = value;
return true;
}
case ZR_CLASS_FLAG_FOV:
{
ClassDataCache[classindex][class_fov] = value;
return true;
}
case ZR_CLASS_FLAG_IMMUNITY_MODE:
{
ClassDataCache[classindex][class_fov] = value;
return true;
}
case ZR_CLASS_FLAG_HEALTH:
{
if (ismultiplier)
{
value = RoundToNearest(float(ClassData[classindex][class_health]) * multiplier);
}
ClassDataCache[classindex][class_health] = value;
return true;
}
case ZR_CLASS_FLAG_HEALTH_REGEN_AMOUNT:
{
if (ismultiplier)
{
value = RoundToNearest(float(ClassData[classindex][class_health_regen_amount]) * multiplier);
}
ClassDataCache[classindex][class_health_regen_amount] = value;
return true;
}
case ZR_CLASS_FLAG_HEALTH_INFECT_GAIN:
{
if (ismultiplier)
{
value = RoundToNearest(float(ClassData[classindex][class_health_infect_gain]) * multiplier);
}
ClassDataCache[classindex][class_health_infect_gain] = value;
return true;
}
case ZR_CLASS_FLAG_KILL_BONUS:
{
if (ismultiplier)
{
value = RoundToNearest(float(ClassData[classindex][class_kill_bonus]) * multiplier);
}
ClassDataCache[classindex][class_kill_bonus] = value;
return true;
}
}
// Invalid flag or multiple flags combined.
return false;
}
/**
* Modify class float attribute on a class.
*
* @param classindex The class index.
* @param attributeflag Attribute to modify (a single attribute flag).
* @param value New value to set, or multiply with.
* @param ismultiplier Optional. Specifies wether to value as a multiplier
* that multiplies with the original class value.
* Not all attributes support multipliers.
* @return True on success, false otherwise.
*/
ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier = false)
{
// Validate class index.
if (!ClassValidateIndex(classindex))
{
return false;
}
switch (attributeflag)
{
case ZR_CLASS_FLAG_NAPALM_TIME:
{
if (ismultiplier)
{
value = ClassData[classindex][class_napalm_time] * value;
}
ClassDataCache[classindex][class_napalm_time] = value;
return true;
}
case ZR_CLASS_FLAG_IMMUNITY_AMOUNT:
{
if (ismultiplier)
{
value = ClassData[classindex][class_immunity_amount] * value;
}
ClassDataCache[classindex][class_immunity_amount] = value;
return true;
}
case ZR_CLASS_FLAG_HEALTH_REGEN_INTERVAL:
{
if (ismultiplier)
{
value = ClassData[classindex][class_health_regen_interval] * value;
}
ClassDataCache[classindex][class_health_regen_interval] = value;
return true;
}
case ZR_CLASS_FLAG_SPEED:
{
if (ismultiplier)
{
value = ClassData[classindex][class_speed] * value;
}
ClassDataCache[classindex][class_speed] = value;
return true;
}
case ZR_CLASS_FLAG_KNOCKBACK:
{
if (ismultiplier)
{
value = ClassData[classindex][class_knockback] * value;
}
ClassDataCache[classindex][class_knockback] = value;
return true;
}
case ZR_CLASS_FLAG_JUMP_HEIGHT:
{
if (ismultiplier)
{
value = ClassData[classindex][class_jump_height] * value;
}
ClassDataCache[classindex][class_jump_height] = value;
return true;
}
case ZR_CLASS_FLAG_JUMP_DISTANCE:
{
if (ismultiplier)
{
value = ClassData[classindex][class_jump_distance] * value;
}
ClassDataCache[classindex][class_jump_distance] = value;
return true;
}
}
// Invalid flag or multiple flags combined.
return false;
}
/**
* Modify class string attribute on a class.
*
* @param classindex The class index.
* @param attributeflag Attribute to modify (a single attribute flag).
* @param value New value to set.
* @return True on success, false otherwise.
*/
ClassModifyString(classindex, attributeflag, const String:value[])
{
// Validate class index.
if (!ClassValidateIndex(classindex))
{
return false;
}
switch (attributeflag)
{
case ZR_CLASS_FLAG_NAME:
{
strcopy(ClassDataCache[classindex][class_name], 64, value);
return true;
}
case ZR_CLASS_FLAG_DESCRIPTION:
{
strcopy(ClassDataCache[classindex][class_description], 256, value);
return true;
}
case ZR_CLASS_FLAG_MODEL_PATH:
{
strcopy(ClassDataCache[classindex][class_model_path], PLATFORM_MAX_PATH, value);
return true;
}
case ZR_CLASS_FLAG_OVERLAY_PATH:
{
strcopy(ClassDataCache[classindex][class_overlay_path], PLATFORM_MAX_PATH, value);
return true;
}
}
// Invalid flag or multiple flags combined.
return false;
}