Skip to content

Chapter 1.3: Classes & Inheritance

Home | << Previous: Arrays, Maps & Sets | Classes & Inheritance | Next: Modded Classes >>


Introdução

Tudo no DayZ é uma classe. Toda arma, veículo, zumbi, painel de UI, gerenciador de config e jogador é uma instância de uma classe. Entender como declarar, estender e trabalhar com classes em Enforce Script é a base de todo modding para DayZ.

O sistema de classes do Enforce Script é de herança simples, orientado a objetos, com modificadores de acesso, construtores, destrutores, membros estáticos e override de métodos. Se você conhece C# ou Java, os conceitos são familiares --- mas a sintaxe tem seu próprio estilo, e existem diferenças importantes abordadas neste capítulo.


Declarando uma Classe

Uma classe agrupa dados relacionados (campos) e comportamento (métodos) juntos.

c
class ZombieTracker
{
    // Fields (member variables)
    int m_ZombieCount;
    float m_SpawnRadius;
    string m_ZoneName;
    bool m_IsActive;
    vector m_CenterPos;

    // Methods (member functions)
    void Activate(vector center, float radius)
    {
        m_CenterPos = center;
        m_SpawnRadius = radius;
        m_IsActive = true;
    }

    bool IsActive()
    {
        return m_IsActive;
    }

    float GetDistanceToCenter(vector pos)
    {
        return vector.Distance(m_CenterPos, pos);
    }
}

Convenções de Nomenclatura de Classes

O modding de DayZ segue estas convenções:

  • Nomes de classes: PascalCase (ex: PlayerTracker, LootManager)
  • Campos de membro: prefixo m_PascalCase (ex: m_Health, m_PlayerList)
  • Campos estáticos: prefixo s_PascalCase (ex: s_Instance, s_Counter)
  • Constantes: UPPER_SNAKE_CASE (ex: MAX_HEALTH, DEFAULT_RADIUS)
  • Métodos: PascalCase (ex: GetPosition(), SetHealth())
  • Variáveis locais: camelCase (ex: playerCount, nearestDist)

Criando e Usando Instâncias

c
void Example()
{
    // Create an instance with 'new'
    ZombieTracker tracker = new ZombieTracker;

    // Call methods
    tracker.Activate(Vector(5000, 0, 8000), 200.0);

    if (tracker.IsActive())
    {
        float dist = tracker.GetDistanceToCenter(Vector(5050, 0, 8050));
        Print(string.Format("Distance: %1", dist));
    }

    // Destroy an instance with 'delete' (usually not needed; see Memory section)
    delete tracker;
}

Construtores e Destrutores

Construtores inicializam um objeto quando ele é criado. Destrutores fazem limpeza quando ele é destruído. Em Enforce Script, ambos usam o nome da classe --- o destrutor é prefixado com ~.

Construtor

c
class SpawnZone
{
    protected string m_Name;
    protected vector m_Position;
    protected float m_Radius;
    protected ref array<string> m_AllowedTypes;

    // Constructor: same name as the class
    void SpawnZone(string name, vector pos, float radius)
    {
        m_Name = name;
        m_Position = pos;
        m_Radius = radius;
        m_AllowedTypes = new array<string>;

        Print(string.Format("[SpawnZone] Created: %1 at %2, radius %3", m_Name, m_Position, m_Radius));
    }

    // Destructor: ~ prefix
    void ~SpawnZone()
    {
        Print(string.Format("[SpawnZone] Destroyed: %1", m_Name));
        // m_AllowedTypes is a ref, it will be deleted automatically
    }

    void AddAllowedType(string typeName)
    {
        m_AllowedTypes.Insert(typeName);
    }
}

Construtor Padrão (Sem Parâmetros)

Se você não definir um construtor, a classe recebe um construtor padrão implícito que inicializa todos os campos com seus valores padrão (0, 0.0, false, "", null).

c
class SimpleConfig
{
    int m_MaxPlayers;      // initialized to 0
    float m_SpawnDelay;    // initialized to 0.0
    string m_ServerName;   // initialized to ""
    bool m_PvPEnabled;     // initialized to false
}

void Test()
{
    SimpleConfig cfg = new SimpleConfig;
    // All fields are at their defaults
    Print(cfg.m_MaxPlayers);  // 0
}

Sobrecarga de Construtores

Você pode definir múltiplos construtores com diferentes listas de parâmetros:

c
class DamageEvent
{
    protected float m_Amount;
    protected string m_Source;
    protected vector m_Position;

    // Constructor with all parameters
    void DamageEvent(float amount, string source, vector pos)
    {
        m_Amount = amount;
        m_Source = source;
        m_Position = pos;
    }

    // Simpler constructor with defaults
    void DamageEvent(float amount)
    {
        m_Amount = amount;
        m_Source = "Unknown";
        m_Position = vector.Zero;
    }
}

void Test()
{
    DamageEvent full = new DamageEvent(50.0, "AKM", Vector(100, 0, 200));
    DamageEvent simple = new DamageEvent(25.0);
}

Modificadores de Acesso

Modificadores de acesso controlam quem pode ver e usar campos e métodos.

ModificadorAcessível DeSintaxe
privateApenas a classe declaranteprivate int m_Secret;
protectedClasse declarante + todas as subclassesprotected int m_Health;
(nenhum)Qualquer lugar (público)int m_Value;

Não existe a palavra-chave public explícita --- tudo sem private ou protected é público por padrão.

c
class BaseVehicle
{
    // Public: anyone can access
    string m_DisplayName;

    // Protected: this class and subclasses only
    protected float m_Fuel;
    protected float m_MaxFuel;

    // Private: only this exact class
    private int m_InternalState;

    void BaseVehicle(string name, float maxFuel)
    {
        m_DisplayName = name;
        m_MaxFuel = maxFuel;
        m_Fuel = maxFuel;
        m_InternalState = 0;
    }

    // Public method
    float GetFuelPercent()
    {
        return (m_Fuel / m_MaxFuel) * 100.0;
    }

    // Protected method: subclasses can call this
    protected void ConsumeFuel(float amount)
    {
        m_Fuel = Math.Clamp(m_Fuel - amount, 0, m_MaxFuel);
    }

    // Private method: only this class
    private void UpdateInternalState()
    {
        m_InternalState++;
    }
}

Boa Prática: Encapsulamento

Exponha campos através de métodos (getters/setters) em vez de torná-los públicos. Isso permite adicionar validação, logging ou efeitos colaterais depois sem quebrar o código que usa a classe.

c
class PlayerStats
{
    protected float m_Health;
    protected float m_MaxHealth;

    void PlayerStats(float maxHealth)
    {
        m_MaxHealth = maxHealth;
        m_Health = maxHealth;
    }

    // Getter
    float GetHealth()
    {
        return m_Health;
    }

    // Setter with validation
    void SetHealth(float value)
    {
        m_Health = Math.Clamp(value, 0, m_MaxHealth);
    }

    // Convenience methods
    void TakeDamage(float amount)
    {
        SetHealth(m_Health - amount);
    }

    void Heal(float amount)
    {
        SetHealth(m_Health + amount);
    }

    bool IsAlive()
    {
        return m_Health > 0;
    }
}

Herança

Herança permite criar uma nova classe baseada em uma existente. A classe filha herda todos os campos e métodos da classe pai, e pode adicionar novos ou sobrescrever o comportamento existente.

Sintaxe: extends ou :

Enforce Script suporta duas sintaxes para herança. Ambas são equivalentes:

c
// Syntax 1: extends keyword (preferred, more readable)
class Car extends BaseVehicle
{
}

// Syntax 2: colon (C++ style, also common in DayZ code)
class Truck : BaseVehicle
{
}

Exemplo Básico de Herança

c
class Animal
{
    protected string m_Name;
    protected float m_Health;

    void Animal(string name, float health)
    {
        m_Name = name;
        m_Health = health;
    }

    string GetName()
    {
        return m_Name;
    }

    void Speak()
    {
        Print(m_Name + " makes a sound");
    }
}

class Dog extends Animal
{
    protected string m_Breed;

    void Dog(string name, string breed)
    {
        // Note: parent constructor is called automatically with no args,
        // or you can initialize parent fields directly since they are protected
        m_Name = name;
        m_Health = 100.0;
        m_Breed = breed;
    }

    string GetBreed()
    {
        return m_Breed;
    }

    // New method only in Dog
    void Fetch()
    {
        Print(m_Name + " fetches the stick!");
    }
}

void Test()
{
    Dog rex = new Dog("Rex", "German Shepherd");
    rex.Speak();         // Inherited from Animal: "Rex makes a sound"
    rex.Fetch();         // Dog's own method: "Rex fetches the stick!"
    Print(rex.GetName()); // Inherited: "Rex"
    Print(rex.GetBreed()); // Dog's own: "German Shepherd"
}

Apenas Herança Simples

Enforce Script suporta apenas herança simples. Uma classe pode estender exatamente um pai. Não existe herança múltipla, interfaces ou mixins.

c
class A { }
class B extends A { }     // OK: single parent
// class C extends A, B { }  // ERROR: multiple inheritance not supported
class D extends B { }     // OK: B extends A, D extends B (inheritance chain)

A Palavra-chave sealed (1.28+)

Uma classe marcada como sealed nao pode ser herdada. Um metodo marcado como sealed nao pode ser sobrescrito. O DayZ 1.28 impoe isso em tempo de compilacao.

c
sealed class FinalClass
{
    void DoWork()
    {
        // This class cannot be extended
    }
}

class MyChild : FinalClass  // ERRO DE COMPILACAO: nao pode herdar de classe sealed
{
}

Metodos tambem podem ser marcados como sealed individualmente:

c
class MyBase
{
    sealed void LockedMethod()
    {
        // Cannot be overridden in child classes
    }

    void OpenMethod()
    {
        // Can be overridden normally
    }
}

Nota de migracao: Se voce atualizar para o DayZ 1.28 e receber um erro de compilacao sobre herdar de uma classe sealed, voce deve refatorar. Use composicao (encapsule a classe como membro) em vez de heranca.

sealed e raramente usado em modding de DayZ ja que extensibilidade e o objetivo principal.


Sobrescrevendo Métodos

Quando uma subclasse precisa mudar o comportamento de um método herdado, ela usa a palavra-chave override. O compilador verifica se a assinatura do método corresponde a um método na classe pai.

c
class Weapon
{
    protected string m_Name;
    protected float m_Damage;

    void Weapon(string name, float damage)
    {
        m_Name = name;
        m_Damage = damage;
    }

    float CalculateDamage(float distance)
    {
        // Base damage, no falloff
        return m_Damage;
    }

    string GetInfo()
    {
        return string.Format("%1 (Dmg: %2)", m_Name, m_Damage);
    }
}

class Rifle extends Weapon
{
    protected float m_MaxRange;

    void Rifle(string name, float damage, float maxRange)
    {
        m_Name = name;
        m_Damage = damage;
        m_MaxRange = maxRange;
    }

    // Override: change damage calculation to include distance falloff
    override float CalculateDamage(float distance)
    {
        float falloff = Math.Clamp(1.0 - (distance / m_MaxRange), 0.1, 1.0);
        return m_Damage * falloff;
    }

    // Override: add range info
    override string GetInfo()
    {
        return string.Format("%1 (Dmg: %2, Range: %3m)", m_Name, m_Damage, m_MaxRange);
    }
}

A Palavra-chave super

super se refere à classe pai. Use para chamar a versão do método do pai, depois adicione sua própria lógica por cima. Isso é crítico --- especialmente em modded classes.

c
class BaseLogger
{
    void Log(string message)
    {
        Print("[LOG] " + message);
    }
}

class TimestampLogger extends BaseLogger
{
    override void Log(string message)
    {
        // Call parent's Log first
        super.Log(message);

        // Then add timestamp logging
        int hour, minute, second;
        GetHourMinuteSecond(hour, minute, second);
        Print(string.Format("[%1:%2:%3] %4", hour, minute, second, message));
    }
}

Palavra-chave this

this se refere à instância atual do objeto. Geralmente é implícito (você não precisa escrevê-lo), mas pode ser útil para clareza ou ao passar o objeto atual para outra função.

c
class EventManager
{
    void Register(Managed handler) { /* ... */ }
}

class MyPlugin
{
    void Init(EventManager mgr)
    {
        // Pass 'this' (the current MyPlugin instance) to the manager
        mgr.Register(this);
    }
}

Métodos e Campos Estáticos

Membros estáticos pertencem à classe em si, não a qualquer instância. São acessados usando o nome da classe, não uma variável de objeto.

Campos Estáticos

c
class GameConfig
{
    // Static fields: shared across all instances (and accessible without an instance)
    static int s_MaxPlayers = 60;
    static float s_TickRate = 30.0;
    static string s_ServerName = "My Server";

    // Regular (instance) field
    protected bool m_IsLoaded;
}

void UseStaticFields()
{
    // Access without creating an instance
    Print(GameConfig.s_MaxPlayers);     // 60
    Print(GameConfig.s_ServerName);     // "My Server"

    // Modify
    GameConfig.s_MaxPlayers = 40;
}

Métodos Estáticos

c
class MathUtils
{
    static float MetersToKilometers(float meters)
    {
        return meters / 1000.0;
    }

    static string FormatDistance(float meters)
    {
        if (meters >= 1000)
            return string.Format("%.1f km", meters / 1000.0);
        else
            return string.Format("%1 m", Math.Round(meters));
    }

    static bool IsInCircle(vector point, vector center, float radius)
    {
        return vector.Distance(point, center) <= radius;
    }
}

void Test()
{
    float km = MathUtils.MetersToKilometers(2500);     // 2.5
    string display = MathUtils.FormatDistance(750);      // "750 m"
    bool inside = MathUtils.IsInCircle("100 0 200", "150 0 250", 100);
}

O Padrão Singleton

O uso mais comum de campos estáticos em mods de DayZ é o padrão singleton: uma classe que tem exatamente uma instância, acessível globalmente.

c
class MyModManager
{
    // Static reference to the single instance
    private static ref MyModManager s_Instance;

    protected bool m_Initialized;
    protected ref array<string> m_Data;

    void MyModManager()
    {
        m_Initialized = false;
        m_Data = new array<string>;
    }

    // Static getter for the singleton
    static MyModManager GetInstance()
    {
        if (!s_Instance)
            s_Instance = new MyModManager;

        return s_Instance;
    }

    void Init()
    {
        if (m_Initialized)
            return;

        m_Initialized = true;
        Print("[MyMod] Manager initialized");
    }

    // Static cleanup
    static void Destroy()
    {
        s_Instance = null;
    }
}

// Usage from anywhere:
void SomeFunction()
{
    MyModManager.GetInstance().Init();
}

Exemplo Real: Classe de Item Personalizado

Aqui está um exemplo completo mostrando uma hierarquia de classe de item personalizado no estilo de modding de DayZ. Isso demonstra tudo que foi abordado neste capítulo.

c
// Base class for all custom medical items
class CustomMedicalBase extends ItemBase
{
    protected float m_HealAmount;
    protected float m_UseTime;      // seconds to use
    protected bool m_RequiresBandage;

    void CustomMedicalBase()
    {
        m_HealAmount = 0;
        m_UseTime = 3.0;
        m_RequiresBandage = false;
    }

    float GetHealAmount()
    {
        return m_HealAmount;
    }

    float GetUseTime()
    {
        return m_UseTime;
    }

    bool RequiresBandage()
    {
        return m_RequiresBandage;
    }

    // Can be overridden by subclasses
    void OnApplied(PlayerBase player)
    {
        if (!player)
            return;

        player.AddHealth("", "Health", m_HealAmount);
        Print(string.Format("[Medical] %1 applied, healed %2", GetType(), m_HealAmount));
    }
}

// Specific medical item: Bandage
class CustomBandage extends CustomMedicalBase
{
    void CustomBandage()
    {
        m_HealAmount = 25.0;
        m_UseTime = 2.0;
    }

    override void OnApplied(PlayerBase player)
    {
        super.OnApplied(player);

        // Additional bandage-specific effect: stop bleeding
        // (simplified example)
        Print("[Medical] Bleeding stopped");
    }
}

// Specific medical item: First Aid Kit (heals more, takes longer)
class CustomFirstAidKit extends CustomMedicalBase
{
    private int m_UsesRemaining;

    void CustomFirstAidKit()
    {
        m_HealAmount = 75.0;
        m_UseTime = 8.0;
        m_UsesRemaining = 3;
    }

    int GetUsesRemaining()
    {
        return m_UsesRemaining;
    }

    override void OnApplied(PlayerBase player)
    {
        if (m_UsesRemaining <= 0)
        {
            Print("[Medical] First Aid Kit is empty!");
            return;
        }

        super.OnApplied(player);
        m_UsesRemaining--;

        Print(string.Format("[Medical] Uses remaining: %1", m_UsesRemaining));
    }
}

config.cpp para Itens Personalizados

A hierarquia de classes no script deve corresponder à herança do config.cpp:

cpp
class CfgVehicles
{
    class ItemBase;

    class CustomMedicalBase : ItemBase
    {
        scope = 0;  // 0 = abstract, cannot be spawned
        displayName = "";
    };

    class CustomBandage : CustomMedicalBase
    {
        scope = 2;  // 2 = public, can be spawned
        displayName = "Custom Bandage";
        descriptionShort = "A sterile bandage for wound treatment.";
        model = "\MyMod\data\bandage.p3d";
        weight = 50;
    };

    class CustomFirstAidKit : CustomMedicalBase
    {
        scope = 2;
        displayName = "Custom First Aid Kit";
        descriptionShort = "A complete first aid kit with multiple uses.";
        model = "\MyMod\data\firstaidkit.p3d";
        weight = 300;
    };
};

A Hierarquia de Classes do DayZ

Entender a hierarquia de classes vanilla é essencial para modding. Aqui estão as classes mais importantes das quais você vai herdar ou interagir:

Class                          // Root of all reference types
  Managed                      // Prevents engine ref-counting (use for pure script classes)
  IEntity                      // Engine entity base
    Object                     // Anything with a position in the world
      Entity
        EntityAI               // Has inventory, health, actions
          InventoryItem
            ItemBase           // ALL items (inherit from this for custom items)
              Weapon_Base      // All weapons
              Magazine_Base    // All magazines
              Clothing_Base    // All clothing
          Transport
            CarScript          // All vehicles
          DayZCreatureAI
            DayZInfected       // Zombies
            DayZAnimal         // Animals
          Man
            DayZPlayer
              PlayerBase       // THE player class (modded constantly)
                SurvivorBase   // Character appearance

Classes Base Comuns para Modding

Se você quer criar...Estenda...
Um novo itemItemBase
Uma nova armaWeapon_Base
Uma nova peça de roupaClothing_Base
Um novo veículoCarScript
Um elemento de UIUIScriptedMenu ou ScriptedWidgetEventHandler
Um gerenciador/sistemaManaged
Uma classe de dados de configManaged
Um hook de missionMissionServer ou MissionGameplay (via modded class)

Erros Comuns

1. Esquecendo ref para Objetos Próprios

Quando uma classe possui outro objeto (cria-o, é responsável pelo seu ciclo de vida), declare o campo como ref. Sem ref, o objeto pode ser coletado pelo garbage collector inesperadamente.

c
// BAD: m_Data might be garbage collected
class BadManager
{
    array<string> m_Data;  // raw pointer, no ownership

    void BadManager()
    {
        m_Data = new array<string>;  // object might get collected
    }
}

// GOOD: ref ensures the manager keeps m_Data alive
class GoodManager
{
    ref array<string> m_Data;  // strong reference, owns the object

    void GoodManager()
    {
        m_Data = new array<string>;
    }
}

2. Esquecendo a Palavra-chave override

Se você pretende sobrescrever um método do pai mas esquece a palavra-chave override, você obtém um novo método que esconde o método do pai em vez de substituí-lo. O compilador pode alertar sobre isso.

c
class Parent
{
    void DoWork() { Print("Parent"); }
}

class Child extends Parent
{
    // BAD: creates a new method, doesn't override
    void DoWork() { Print("Child"); }

    // GOOD: properly overrides
    override void DoWork() { Print("Child"); }
}

3. Não Chamar super em Overrides

Quando você sobrescreve um método, o código do pai NÃO é chamado automaticamente. Se você pular o super, perde o comportamento do pai --- o que pode quebrar funcionalidades, especialmente nas cadeias profundas de herança do DayZ.

c
class Parent
{
    void Init()
    {
        // Critical initialization happens here
        Print("Parent.Init()");
    }
}

class Child extends Parent
{
    // BAD: Parent.Init() never runs
    override void Init()
    {
        Print("Child.Init()");
    }

    // GOOD: Parent.Init() runs first, then child adds behavior
    override void Init()
    {
        super.Init();
        Print("Child.Init()");
    }
}

4. Ciclos de Ref Causam Vazamento de Memória

Se o objeto A mantém um ref para o objeto B, e o objeto B mantém um ref para o objeto A, nenhum pode ser liberado. Um lado deve usar um ponteiro raw (sem ref).

c
// BAD: ref cycle, neither object can be freed
class Parent
{
    ref Child m_Child;
}
class Child
{
    ref Parent m_Parent;  // LEAK: circular ref
}

// GOOD: child holds a raw pointer to parent
class Parent2
{
    ref Child2 m_Child;
}
class Child2
{
    Parent2 m_Parent;  // raw pointer, no ref -- breaks the cycle
}

5. Tentando Usar Herança Múltipla

Enforce Script não suporta herança múltipla. Se você precisa compartilhar comportamento entre classes não relacionadas, use composição (mantenha uma referência a um objeto auxiliar) ou métodos utilitários estáticos.

c
// CANNOT DO THIS:
// class FlyingCar extends Car, Aircraft { }  // ERROR

// Instead, use composition:
class FlyingCar extends Car
{
    protected ref FlightController m_Flight;

    void FlyingCar()
    {
        m_Flight = new FlightController;
    }

    void Fly(vector destination)
    {
        m_Flight.NavigateTo(destination);
    }
}

Boas Praticas

  • Sempre chame super.MethodName() em overrides a menos que voce intencionalmente queira substituir o comportamento do pai por completo -- as cadeias profundas de heranca do DayZ dependem disso.
  • Use protected para campos de membro e exponha-os via metodos getter/setter -- isso permite adicionar validacao ou logging depois sem quebrar os chamadores.
  • Prefira composicao sobre heranca profunda ao combinar comportamentos nao relacionados (ex.: um controlador de voo dentro de um veiculo, nao uma tentativa de heranca multipla FlyingCar).
  • Marque membros de objetos possuidos com ref na declaracao -- sem isso, o objeto pode ser coletado pelo garbage collector enquanto sua classe ainda o espera.
  • Use o padrao singleton (static ref + GetInstance()) para classes gerenciadoras que devem ter exatamente uma instancia.

Observado em Mods Reais

Padroes confirmados pelo estudo de codigo-fonte de mods profissionais de DayZ.

PadraoModDetalhe
Singleton via static ref + GetInstance()COT / ExpansionTodo gerenciador importante (permissoes, notificacoes, mercado) segue exatamente este padrao
Construtor inicializa todas as colecoes refDabs FrameworkConstrutores sempre criam new array / new map para cada membro ref
override + super em todo metodo de ciclo de vidaVPP AdminOnInit, OnMissionStart, OnUpdate sempre chamam super primeiro, depois adicionam comportamento
Base abstrata com scope=0 no config.cppExpansion VehiclesClasse de script de veiculo base tem scope=0 (nao pode spawnar), subclasses concretas tem scope=2

Teoria vs Pratica

ConceitoTeoriaRealidade
Omitir a palavra-chave overrideDeveria criar um novo metodoFrequentemente cria um bug sutil onde o metodo do pai roda em vez do da filha
Multiplos construtores (sobrecarga)Recurso OOP padraoFunciona mas raramente usado em mods de DayZ -- a maioria das classes usa um unico construtor com valores padrao
Classes/metodos sealedPrevine heranca ou override (imposto em tempo de compilacao desde 1.28)Quase nunca usado em modding de DayZ porque extensibilidade e o objetivo principal

Exercícios Práticos

Exercício 1: Hierarquia de Formas

Crie uma classe base Shape com um método float GetArea(). Crie subclasses Circle (raio), Rectangle (largura, altura) e Triangle (base, altura) que sobrescrevem GetArea(). Imprima a área de cada uma.

Exercício 2: Sistema de Logger

Crie uma classe Logger com um método Log(string message) que imprime no console. Crie FileLogger que a estende e também escreve em um arquivo conceitual (apenas imprima com prefixo [FILE]). Crie DiscordLogger que estende Logger e adiciona um prefixo [DISCORD]. Cada um deve chamar super.Log().

Exercício 3: Item de Inventário

Crie uma classe CustomItem com campos protegidos para m_Weight, m_Value e m_Condition (float 0-1). Inclua:

  • Um construtor que recebe todos os três valores
  • Getters para cada campo
  • Um método Degrade(float amount) que reduz a condição (limitado a 0)
  • Um método GetEffectiveValue() que retorna m_Value * m_Condition

Depois crie CustomWeaponItem que a estende, adicionando m_Damage e um override de GetEffectiveValue() que incorpora o dano.

Exercício 4: Gerenciador Singleton

Implemente um singleton SessionManager que rastreia eventos de entrada/saída de jogadores. Deve armazenar tempos de entrada em um map e fornecer métodos:

  • OnPlayerJoin(string uid, string name)
  • OnPlayerLeave(string uid)
  • int GetOnlineCount()
  • float GetSessionDuration(string uid) (em segundos)

Exercício 5: Cadeia de Comando

Crie uma classe abstrata Handler com protected Handler m_Next e métodos SetNext(Handler next) e void Handle(string request). Crie três handlers concretos (AuthHandler, PermissionHandler, ActionHandler) que tratam a requisição ou passam para m_Next. Demonstre a cadeia.


Resumo

ConceitoSintaxeObservações
Declaração de classeclass Name { }Membros públicos por padrão
Herançaclass Child extends ParentApenas herança simples; também : Parent
Construtorvoid ClassName()Mesmo nome que a classe
Destrutorvoid ~ClassName()Chamado na exclusão
Privateprivate int m_Field;Apenas esta classe
Protectedprotected int m_Field;Esta classe + subclasses
Publicint m_Field;Sem palavra-chave necessária (padrão)
Overrideoverride void Method()Deve corresponder à assinatura do pai
Chamada supersuper.Method()Chama a versão do pai
Campo estáticostatic int s_Count;Compartilhado entre todas as instâncias
Método estáticostatic void DoThing()Chamado via ClassName.DoThing()
refref MyClass m_Obj;Referência forte (possui o objeto)
Classe sealedsealed class Name { }Nao pode ser herdada (erro de compilacao no 1.28+)
Metodo sealedsealed void Method()Nao pode ser sobrescrito em classes filhas
Proto nativeproto native void Func();Metodo implementado na engine
Parametro outvoid Func(out int val)Parametro somente de saida
Parametro inoutvoid Func(inout array<int> a)Parametro de entrada + saida
Parametro notnullvoid Func(notnull EntityAI e)Non-null imposto pelo compilador

Início | << Anterior: Arrays, Maps & Sets | Classes & Herança | Próximo: Modded Classes >>

Released under CC BY-SA 4.0 | Code examples under MIT License