• Рекомендуем зарегистрироваться для просмотра контента и скачивания файлов!

Практическое использование мутатора VipItemMut(Вип Броня)

denfil777

Патриарх
Команда форума
Регистрация
12 Янв 2024
Сообщения
74
Реакции
10
Баллы
8
Броня для Vip игрока

Для начала так поправим ServerPerks, чтобы у вип игрока
1. при появлении было 150 брони (пока решил не делать этот пункт, подробности ниже)
2. в магазине закупка брони была до 150 (при этом 150 всё равно будет 100%, просто 100 брони будет считаться 66%)
3. при подъёме брони с земли она пополнялась бы до 150
4. правильно отображалась полосочка брони в HUD

Рассмотрим подробнее эти исправления

0. Создадим класс утилит - Utilities.
Там будем складировать полезные static функции, которые вызываются из разных кусков кода.
Пока добавим одну только функцию HasItem, которая проверяет есть ли у игрока P в инвентаре что-то под именем ItemName.

Код:
class Utilities extends Actor
    abstract;

//Проверка есть ли у игрока P в инвентаре что-то под именем ItemName
static function bool HasItem(Pawn P, Name ItemName)
{
    local Inventory Inv;
    for(Inv=P.Inventory;Inv!=None;Inv=Inv.Inventory)
    {
        if(Inv.Name==ItemName)
            return true;
    }
    return false;
}
Появление с бронёй
Решил опустить этот пункт. Во-первых, этот бонус выбивается из общей концепции, где мы правим ёмкость брони - задание конкретного значения это дело настроек каждого перка.
Во-вторых, у меня сходу не получилось придумать изящное решение, а громоздить некрасивый код я не хочу)

2. Покупка брони
Отображение в магазине:
Правим класс SRKFBuyMenuInvList, функцию UpdateMyBuyables
Добавляем переменную ShieldItemAmmoMax и в зависимости от того вип или нет присваиваем этой переменной значения 150 или 100.
И в дальнейшем в стандартном коде этой функции заменяем 100 на ShieldItemAmmoMax в кусочке относящимся к броне.
Код:
function UpdateMyBuyables()
{
    ...
    local float ShieldItemAmmoMax;
    ...
    ...
    if    (
            PlayerOwner()!=none
            &&    class'Utilities'.static.HasItem(PlayerOwner().Pawn,'VipItem')
        )
    {
        ShieldItemAmmoMax=150.0;
    }
    else
        ShieldItemAmmoMax=100.0;

    MyBuyable.ItemName         = class'BuyableVest'.default.ItemName;
    MyBuyable.ItemDescription    = class'BuyableVest'.default.ItemDescription;
    MyBuyable.ItemCategorie        = "";
    MyBuyable.ItemImage        = class'BuyableVest'.default.ItemImage;
    MyBuyable.ItemAmmoCurrent    = PlayerOwner().Pawn.ShieldStrength;
    MyBuyable.ItemAmmoMax        = ShieldItemAmmoMax;
    MyBuyable.ItemCost        = int(class'BuyableVest'.default.ItemCost * KFV.static.GetCostScaling(PRI, class'Vest'));
    MyBuyable.ItemAmmoCost        = MyBuyable.ItemCost / ShieldItemAmmoMax;
    MyBuyable.ItemFillAmmoCost    = int((ShieldItemAmmoMax - MyBuyable.ItemAmmoCurrent) * MyBuyable.ItemAmmoCost);
    MyBuyable.bIsVest            = true;
    MyBuyable.bMelee            = false;
    MyBuyable.bSaleList        = false;
    MyBuyable.bSellable        = false;
    MyBuyable.ItemPerkIndex        = class'BuyableVest'.default.CorrespondingPerkIndex;
    ...
}
Фактическая реализация покупки:
Правим класс SRHumanPawn, функцию ServerBuyKevlar
Как и в прошлом случае создаём переменную, которая будет хранить 100 или 150. Пусть она называется cShield.
И в стандартном коде заменяем 100 на cShield.
Код:
переменную, которая будет хранить 100 или 150. Пусть она называется cShield.
И в стандартном коде заменяем 100 на cShield.
Спойлер
Код:
function ServerBuyKevlar()
{
    local float Cost;
    local int UnitsAffordable;

    local float cShield;

    if(class'Utilities'.static.HasItem(self,'VipItem'))
        cShield=150.0;
    else
        cShield=100.0;
    Cost = class'Vest'.default.ItemCost * ((cShield - ShieldStrength) / cShield);
    if ( KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none)
    {
        Cost *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), class'Vest');
    }
    if ( !CanBuyNow() || ShieldStrength==cShield )
    {
        SetTraderUpdate();
        Return;
    }
    if ( PlayerReplicationInfo.Score >= Cost )
    {
        PlayerReplicationInfo.Score -= Cost;
        ShieldStrength = cShield;
    }
    else if ( ShieldStrength > 0 )
    {
        Cost = class'Vest'.default.ItemCost;
        if ( KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill != none)
        {
            Cost *= KFPlayerReplicationInfo(PlayerReplicationInfo).ClientVeteranSkill.static.GetCostScaling(KFPlayerReplicationInfo(PlayerReplicationInfo), class'Vest');
        }
        Cost /= cShield;
        UnitsAffordable = int(PlayerReplicationInfo.Score / Cost);
        PlayerReplicationInfo.Score -= int(Cost * UnitsAffordable);
        ShieldStrength += UnitsAffordable;
    }
    SetTraderUpdate();
}
Подбор брони с земли
Прежде всего хотелось бы заменить, что в броне (KFMod.Vest) уже прописано сколько брони добавлять игроку - 100
И если мы хотим это изменить, то надо добавить в какой-то мутатор такую строку в ту же функцию PostBeginPlay, например

class'KFMod.Vest'.default.ShieldAmount=150;

Если хотите можете добавить эту строчку в VipItemMut, хотя как по мне так это неправильно. Должен быть порядок на сервере и должен быть какой-то отдельный мутатор для того, чтобы заменять стандартные значения у классов.

Теперь правим класс SRHumanPawn, функцию AddShieldStrength
Идея всё та же. Создаём переменную и заполняем её значением 100 или 150 в зависимости от того есть ли у игрока VipItem.
После этого меняем стандартную функцию, заменяя 100 на cShield.
Код:
function bool AddShieldStrength(int ShieldAmount)
{
    local float cShield;

    if(class'Utilities'.static.HasItem(self,'VipItem'))
        cShield=150.0;
    else
        cShield=100.0;
    if(ShieldStrength >= cShield)
        return false;

    ShieldStrength+=ShieldAmount;
    if(ShieldStrength > cShield)
        ShieldStrength = cShield;
    return true ;
}
Отображение брони в HUD. Точнее заполненность полоски брони игрока с точки зрения других игроков.
Правим класс SRHUDKillingFloor, функцию DrawPlayerInfo
Идея всё та же. Переменная cShield со значениями 100 или 150 и замена стандартного кода.
Код:
function DrawPlayerInfo(Canvas C, Pawn P, float ScreenLocX, float ScreenLocY)
{
    ...
    local float cShield;
    ...
    if(P!=none && class'Utilities'.static.HasItem(P,'VipItem'))
        cShield=150.0;
    else
        cShield=100.0;
    if ( P.ShieldStrength > 0 )
        DrawKFBar(C, ScreenLocX - OffsetX, (ScreenLocY - YL) - 1.5 * BarHeight, FClamp(P.ShieldStrength / cShield, 0, 1), BeaconAlpha, true);
    ...
}
Сварка брони.
Тут уже надо глядеть код сварочного аппарата. Если там тупо добавляется бронь - сами глядите, есть ли там ограничение до 100 и где его заменить на 150. Если же используется функция AddShieldStrength, то достаточно реализовать пункт 3

Изменённые файлы в SP 7.50
Ссылка Ссылка 2

p.s. Как вы заметили раз за разом мы пишем число 150 в коде. Было бы неплохо не писать конкретное число. Можно это количество брони хранить в VipItem в какой-нибудь переменной, а в мутаторе расширить структуру и прописывать там количество брони для каждого игрока.
Есть много способов расширить возможности VipItem с формального информирования до каких-то практических плюшек.
Это вы сами пытайтесь)
Возможно будут статьи на эту тему.

p.p.s Ещё неплохой способ хранить информацию о том является ли игрок випом или нет - переменная в LinkedReplicationInfo.
Экземпляр LinkedReplicationInfo цепляется к обычному PlayerReplicationInfo, но это так же тема отдельной статьи.

p.p.p.s Ну и совсем адский способ - цепляемся к редко используемым переменным Pawn, Contoller или PlayerReplicationInfo и их детей.

Не так давно пришло в голову - нет никакой необходимости увеличивать количество брони
Можно просто улучшить её качество)
Броня в 150 единиц = обычной броне, которая в 1.5 раза сильнее стандартных настроек
Это резко уменьшает количество кода и мороки с бронёй

Нам достаточно в каждый SRVet* класс (или в класс SRVeterancyTypes) добавить изменённую функцию GetBodyArmorDamageModifier
Что-нибудь такое:
Код:
static function float GetBodyArmorDamageModifier(KFPlayerReplicationInfo KFPRI)
{
if(class'Utilities'.static.HasItem(PlayerController(KFPRI.Owner).Pawn,'VipItem'))
}
И мы получим по сути ровно тот же эффект)
Автор Flame.
 
Последнее редактирование:
Сверху Снизу