diff --git a/src/zr/immunityhandler.inc b/src/zr/immunityhandler.inc index 956a846..ef8ed07 100644 --- a/src/zr/immunityhandler.inc +++ b/src/zr/immunityhandler.inc @@ -28,7 +28,7 @@ /** * Current immunity modes. */ -new ImmunityMode:PlayerImmunityMode[MAXPLAYERS + 1] = {Immunity_None, ...}; +//new ImmunityMode:PlayerImmunityMode[MAXPLAYERS + 1] = {Immunity_None, ...}; /** * Timers for handling timed immunity actions. @@ -87,7 +87,7 @@ bool:ImmunityOnClientInfect(client, attacker) } case Immunity_Infect: { - return ImmunityInfectModeHandler(client, attacker); + return ImmunityInfectModeHandler(client); } case Immunity_Delay: { @@ -285,9 +285,9 @@ bool:ImmunityOnClientDamage(client, attacker, &Float:damage) * * @return True if knock back should be blocked, false otherwise. */ -bool:ImmunityOnClientKnockBack(client) +/*bool:ImmunityOnClientKnockBack(client) { -} +}*/ /** * Handles infect mode immunity. @@ -301,7 +301,7 @@ bool:ImmunityOnClientKnockBack(client) * @return True if infection will be handled by this module, false if * infection can be applied instantly. */ -bool:ImmunityInfectModeHandler(client, attacker) +bool:ImmunityInfectModeHandler(client) { //PrintToChatAll("ImmunityInfectModeHandler(client=%d, attacker=%d)", client, attacker); @@ -412,6 +412,18 @@ public Action:ImmunityDelayTimerHandler(Handle:timer, any:client) */ bool:ImmunityShieldModeHandler(client, bool:asZombie = true) { + // Check cooldown. + + // Deploy shield. + if (asZombie) + { + // Enable knock back shield. + } + else + { + // Enable infection shield. + } + return false; } @@ -472,7 +484,18 @@ ImmunityClientSpawn(client) ImmunityOnClientDisconnect(client) { + ImmunityAbortHandler(client); + // Loop through attacker cache and remove client (set to 0). + for (new victim = 0; victim < sizeof(PlayerImmunityAttacker); victim++) + { + if (PlayerImmunityAttacker[victim] == client) + { + // The victim was attacked by this client, but the client is + // disconnecting now. Reset the attacker index to the world index. + PlayerImmunityAttacker[victim] = 0; + } + } } ImmunityOnClientTeam(client) @@ -548,3 +571,50 @@ ImmunityMode:ImmunityStringToMode(const String:mode[]) return Immunity_Invalid; } + +/** + * Converts an immunity mode to a string. + * + * @param mode Mode to convert. + * @param buffer Destination string buffer. + * @param maxlen Size of buffer. + * + * @return Number of cells written. + */ +ImmunityModeToString(ImmunityMode:mode, String:buffer[], maxlen) +{ + if (mode == Immunity_Invalid) + { + return 0; + } + + switch (mode) + { + case Immunity_None: + { + return strcopy(buffer, maxlen, "none"); + } + case Immunity_Full: + { + return strcopy(buffer, maxlen, "full"); + } + case Immunity_Infect: + { + return strcopy(buffer, maxlen, "infect"); + } + case Immunity_Damage: + { + return strcopy(buffer, maxlen, "damage"); + } + case Immunity_Delay: + { + return strcopy(buffer, maxlen, "delay"); + } + case Immunity_Shield: + { + return strcopy(buffer, maxlen, "shield"); + } + } + + return 0; +} diff --git a/src/zr/infect.inc b/src/zr/infect.inc index 61ac578..d61f6de 100644 --- a/src/zr/infect.inc +++ b/src/zr/infect.inc @@ -813,6 +813,7 @@ InfectZombieToHuman(client, bool:respawn = false, bool:protect = false) // Forward event to modules. SEffectsOnClientHuman(client); APIOnClientHumanPost(client, respawn, protect); + ImmunityOnClientHuman(client); } /** diff --git a/src/zr/playerclasses/attributes.inc b/src/zr/playerclasses/attributes.inc index 84d31e2..ea0ee4a 100644 --- a/src/zr/playerclasses/attributes.inc +++ b/src/zr/playerclasses/attributes.inc @@ -1177,6 +1177,10 @@ stock ClassAttributeNameToFlag(const String:attributename[]) { return ZR_CLASS_IMMUNITY_AMOUNT; } + else if (StrEqual(attributename, "immunity_cooldown", false)) + { + return ZR_CLASS_IMMUNITY_COOLDOWN; + } else if (StrEqual(attributename, "no_fall_damage", false)) { return ZR_CLASS_NO_FALL_DAMAGE; @@ -1299,7 +1303,8 @@ stock ClassDataTypes:ClassGetAttributeType(attributeflag) ZR_CLASS_ALPHA_DAMAGED, ZR_CLASS_ALPHA_DAMAGE, ZR_CLASS_FOV, - ZR_CLASS_IMMUNITY_MODE, + ZR_CLASS_IMMUNITY_AMOUNT, + ZR_CLASS_IMMUNITY_COOLDOWN, ZR_CLASS_HEALTH, ZR_CLASS_HEALTH_REGEN_AMOUNT, ZR_CLASS_HEALTH_INFECT_GAIN, @@ -1310,7 +1315,6 @@ stock ClassDataTypes:ClassGetAttributeType(attributeflag) // Float. case ZR_CLASS_NAPALM_TIME, - ZR_CLASS_IMMUNITY_AMOUNT, ZR_CLASS_HEALTH_REGEN_INTERVAL, ZR_CLASS_SPEED, ZR_CLASS_KNOCKBACK, @@ -1325,7 +1329,8 @@ stock ClassDataTypes:ClassGetAttributeType(attributeflag) ZR_CLASS_NAME, ZR_CLASS_DESCRIPTION, ZR_CLASS_MODEL_PATH, - ZR_CLASS_OVERLAY_PATH: + ZR_CLASS_OVERLAY_PATH, + ZR_CLASS_IMMUNITY_MODE: { return ClassDataType_String; } diff --git a/src/zr/playerclasses/classcommands.inc b/src/zr/playerclasses/classcommands.inc index 353b825..5295366 100644 --- a/src/zr/playerclasses/classcommands.inc +++ b/src/zr/playerclasses/classcommands.inc @@ -290,7 +290,7 @@ public Action:ClassModifyCommand(client, argc) 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), "is_multiplier: Optional. specifies wether the original value should be multiplied by the specified value. Not all attributes support multipliers. 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); @@ -734,9 +734,22 @@ stock ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0. ClassDataCache[classindex][Class_Fov] = value; return true; } - case ZR_CLASS_IMMUNITY_MODE: + case ZR_CLASS_IMMUNITY_AMOUNT: { - ClassDataCache[classindex][Class_ImmunityMode] = value; + if (ismultiplier) + { + value = ClassData[classindex][Class_ImmunityAmount] * value; + } + ClassDataCache[classindex][Class_ImmunityAmount] = value; + return true; + } + case ZR_CLASS_IMMUNITY_COOLDOWN: + { + if (ismultiplier) + { + value = ClassData[classindex][Class_ImmunityCooldown] * value; + } + ClassDataCache[classindex][Class_ImmunityCooldown] = value; return true; } case ZR_CLASS_HEALTH: @@ -811,15 +824,6 @@ stock ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier ClassDataCache[classindex][Class_NapalmTime] = value; return true; } - case ZR_CLASS_IMMUNITY_AMOUNT: - { - if (ismultiplier) - { - value = ClassData[classindex][Class_ImmunityAmount] * value; - } - ClassDataCache[classindex][Class_ImmunityAmount] = value; - return true; - } case ZR_CLASS_HEALTH_REGEN_INTERVAL: { if (ismultiplier) @@ -914,6 +918,22 @@ stock ClassModifyString(classindex, attributeflag, const String:value[]) strcopy(ClassDataCache[classindex][Class_OverlayPath], PLATFORM_MAX_PATH, value); return true; } + case ZR_CLASS_IMMUNITY_MODE: + { + // Convert to mode. + new ImmunityMode:mode = ImmunityStringToMode(value); + + // Validate. + if (mode != Immunity_Invalid) + { + ClassDataCache[classindex][Class_ImmunityMode] = mode; + return true; + } + else + { + return false; + } + } } // Invalid flag or multiple flags combined. diff --git a/src/zr/volfeatures/volclassedit.inc b/src/zr/volfeatures/volclassedit.inc index 0536f26..8db126f 100644 --- a/src/zr/volfeatures/volclassedit.inc +++ b/src/zr/volfeatures/volclassedit.inc @@ -238,7 +238,7 @@ VolClassEditSetAttribute(dataIndex, const String:attribName[], const String:attr } } - /* Player behaviour */ + /* Player behavior */ else if (StrEqual(attribName, "immunity_mode", false)) { if (VolClassEditSetImmunityMode(dataIndex, attribValue)) @@ -253,6 +253,13 @@ VolClassEditSetAttribute(dataIndex, const String:attribName[], const String:attr return true; } } + else if (StrEqual(attribName, "immunity_cooldown", false)) + { + if (VolClassEditSetImmunityCooldown(dataIndex, attribValue)) + { + return true; + } + } else if (StrEqual(attribName, "no_fall_damage", false)) { if (VolClassEditSetNoFallDamage(dataIndex, attribValue)) @@ -395,14 +402,18 @@ VolClassEditDumpData(dataIndex, String:buffer[], maxlen) Format(linebuffer, sizeof(linebuffer), CLASSEDIT_DUMP_FORMAT, "Napalm time:", valuebuffer); cellswritten += StrCat(buffer, maxlen, linebuffer); - VolClassEditIntToString(dataIndex, ClassEdit_ImmunityMode, valuebuffer, sizeof(valuebuffer)); + ImmunityModeToString(VolClassEditData[dataIndex][ClassEdit_ImmunityMode], valuebuffer, sizeof(valuebuffer)); Format(linebuffer, sizeof(linebuffer), CLASSEDIT_DUMP_FORMAT, "Immunity mode:", valuebuffer); cellswritten += StrCat(buffer, maxlen, linebuffer); - VolClassEditFloatToString(dataIndex, ClassEdit_ImmunityAmount, valuebuffer, sizeof(valuebuffer)); + VolClassEditIntToString(dataIndex, ClassEdit_ImmunityAmount, valuebuffer, sizeof(valuebuffer)); Format(linebuffer, sizeof(linebuffer), CLASSEDIT_DUMP_FORMAT, "Immunity amount:", valuebuffer); cellswritten += StrCat(buffer, maxlen, linebuffer); + VolClassEditIntToString(dataIndex, ClassEdit_ImmunityCooldown, valuebuffer, sizeof(valuebuffer)); + Format(linebuffer, sizeof(linebuffer), CLASSEDIT_DUMP_FORMAT, "Immunity cooldown:", valuebuffer); + cellswritten += StrCat(buffer, maxlen, linebuffer); + VolClassEditIntToString(dataIndex, ClassEdit_NoFallDamage, valuebuffer, sizeof(valuebuffer)); Format(linebuffer, sizeof(linebuffer), CLASSEDIT_DUMP_FORMAT, "No fall damage:", valuebuffer); cellswritten += StrCat(buffer, maxlen, linebuffer); @@ -922,7 +933,8 @@ bool:VolClassEditSetImmunityMode(dataIndex, const String:value[]) return false; } - VolClassEditData[dataIndex][VolClassEdit_ClassData][ClassEdit_ImmunityMode] = StringToInt(value); + new ImmunityMode:mode = ImmunityStringToMode(value); + VolClassEditData[dataIndex][VolClassEdit_ClassData][ClassEdit_ImmunityMode] = mode; return true; } @@ -943,7 +955,28 @@ bool:VolClassEditSetImmunityAmount(dataIndex, const String:value[]) return false; } - VolClassEditData[dataIndex][VolClassEdit_ClassData][ClassEdit_ImmunityAmount] = StringToFloat(value); + VolClassEditData[dataIndex][VolClassEdit_ClassData][ClassEdit_ImmunityAmount] = StringToInt(value); + return true; +} + +/** + * Sets the immunity cooldown attribute. + * + * Note: The value is not validated! + * + * @param dataIndex Local data index. + * @param value String value to set (converted to proper type by this + * function). + * @return True if set, false if empty. + */ +bool:VolClassEditSetImmunityCooldown(dataIndex, const String:value[]) +{ + if (strlen(value) == 0) + { + return false; + } + + VolClassEditData[dataIndex][VolClassEdit_ClassData][ClassEdit_ImmunityCooldown] = StringToInt(value); return true; } @@ -1193,19 +1226,26 @@ VolClassEditUpdateAttributes(client, const attributes[]) } // Immunity mode. - if (attributes[ClassEdit_ImmunityMode] > -1) + if (attributes[ClassEdit_ImmunityMode] != Immunity_Invalid) { ClassPlayerCache[client][Class_ImmunityMode] = attributes[ClassEdit_ImmunityMode]; numChanges++; } // Immunity amount. - if (attributes[ClassEdit_ImmunityAmount] > -1.0) + if (attributes[ClassEdit_ImmunityAmount] > -1) { ClassPlayerCache[client][Class_ImmunityAmount] = attributes[ClassEdit_ImmunityAmount]; numChanges++; } + // Immunity cooldown. + if (attributes[ClassEdit_ImmunityCooldown] > -1) + { + ClassPlayerCache[client][Class_ImmunityCooldown] = attributes[ClassEdit_ImmunityCooldown]; + numChanges++; + } + // No fall damage. if (attributes[ClassEdit_NoFallDamage] > -1) { @@ -1331,7 +1371,7 @@ VolClassEditRestoreAttributes(client, classindex, const attributes[]) } // Immunity mode. - if (attributes[ClassEdit_ImmunityMode] > -1) + if (attributes[ClassEdit_ImmunityMode] != Immunity_Invalid) { ClassPlayerCache[client][Class_ImmunityMode] = ClassGetImmunityMode(classindex, ZR_CLASS_CACHE_MODIFIED); numChanges++;