Skip to content

API Entity Flags

WatIsDeze edited this page Dec 9, 2025 · 1 revision

API Reference - Entity Flags

Entity flags control special behaviors and rendering effects. They are defined in src/baseq2rtxp/sharedgame/sg_entity_flags.h.

Overview

Entity flags (entity_state_t::effects) are bit flags sent to clients that control visual effects and entity behavior. They're applied using bitwise operations.

Location: src/baseq2rtxp/sharedgame/sg_entity_flags.h

Flag Categories

Rendering Effects

These flags control how entities are rendered on the client:

#define EF_ROTATE           BIT(1)   // Rotate (bonus items)
#define EF_GIB              BIT(2)   // Leave a trail (blood)
#define EF_ANIM_CYCLE2_2HZ  BIT(3)   // Cycle frames 0-1 at 2 Hz
#define EF_ANIM01           BIT(4)   // Cycle frames 0-1 at 2 Hz
#define EF_ANIM23           BIT(5)   // Cycle frames 2-3 at 2 Hz
#define EF_ANIM_ALL         BIT(6)   // Cycle all frames at 2 Hz
#define EF_ANIM_ALLFAST     BIT(7)   // Cycle all frames at 10 Hz

Power-Up Effects

These flags indicate active power-ups:

#define EF_COLOR_SHELL      BIT(8)   // Colored shell effect
#define EF_QUAD             BIT(9)   // Quad damage glow
#define EF_PENT             BIT(10)  // Pentagram of protection
#define EF_DOUBLE           BIT(11)  // Double damage
#define EF_HALF_DAMAGE      BIT(12)  // Half damage taken

Special Effects

#define EF_TELEPORTER       BIT(13)  // Teleporter particle fountain

Entity Event Targeting

#define EF_ENTITY_EVENT_TARGET_OTHER  BIT(14)  // Event targets another entity

Reserved/Unused

#define EF_UNUSED_15 through EF_UNUSED_31  // Available for custom use

Common Flag Usage

Rotating Items

Make pickup items spin:

void svg_item_health_t::Spawn() {
    s.effects |= EF_ROTATE;  // Item rotates continuously
    s.entityType = ET_ITEM;
}

Client Behavior: Item rotates around Z-axis at constant speed

Animated Lights

Create blinking or animated lights:

void svg_light_blink_t::Spawn() {
    s.effects |= EF_ANIM01;  // Blink between frames 0 and 1
}

void svg_light_strobe_t::Spawn() {
    s.effects |= EF_ANIM_ALLFAST;  // Fast animation through all frames
}

Frame Cycling Speeds:

  • EF_ANIM01, EF_ANIM23, EF_ANIM_ALL: 2 Hz (2 cycles per second)
  • EF_ANIM_ALLFAST: 10 Hz (10 cycles per second)

Gib Trails

Make gibs leave blood trails:

void SVG_ThrowGib(/*...*/) {
    gib->s.effects |= EF_GIB;  // Leaves blood particle trail
    gib->movetype = MOVETYPE_BOUNCE;
}

Client Behavior: Spawns blood particles along movement path

Power-Up Glows

Indicate active power-ups on players:

void svg_player_edict_t::PickupQuad() {
    s.effects |= EF_QUAD;  // Blue glow
    // Stacks with other effects
}

void svg_player_edict_t::PickupInvulnerability() {
    s.effects |= EF_PENT;  // Red glow
}

Visual Effects:

  • EF_QUAD: Blue outer glow
  • EF_PENT: Red spinning shell
  • EF_DOUBLE: Green glow
  • EF_HALF_DAMAGE: Yellow glow

Note: These can be combined (bitwise OR) for multiple simultaneous effects.

Color Shells

Custom colored shells around entities:

void svg_player_edict_t::ApplyColorShell(vec3_t color) {
    s.effects |= EF_COLOR_SHELL;
    s.renderfx = RF_SHELL_RED | RF_SHELL_GREEN;  // Yellow shell
}

Requires: Also setting renderfx flags for shell colors

Teleporter Effect

Spawn particle fountain effect:

void svg_misc_teleporter_t::Spawn() {
    s.effects |= EF_TELEPORTER;  // Upward particle stream
}

Client Behavior: Continuous upward particle fountain

Combining Flags

Flags are combined using bitwise OR (|):

// Item that rotates and has animation
s.effects = EF_ROTATE | EF_ANIM_ALL;

// Player with quad damage and invulnerability
s.effects = EF_QUAD | EF_PENT;

// Gib that leaves trail and rotates
s.effects = EF_GIB | EF_ROTATE;

Setting and Clearing Flags

Setting a Flag

// Add flag (preserves other flags)
s.effects |= EF_ROTATE;

// Set multiple flags
s.effects |= (EF_ROTATE | EF_ANIM_ALL);

Clearing a Flag

// Remove flag (preserves other flags)
s.effects &= ~EF_ROTATE;

// Remove multiple flags
s.effects &= ~(EF_ROTATE | EF_ANIM_ALL);

Toggling a Flag

// Toggle on/off
s.effects ^= EF_ANIM01;

// Example: Blinking light
void Think() {
    s.effects ^= EF_ANIM01;  // Toggle between on and off
    nextThinkTime = level.time + gametime_t::from_sec(0.5f);
}

Checking a Flag

// Check if flag is set
if (s.effects & EF_ROTATE) {
    gi.dprintf("Entity is rotating\n");
}

// Check multiple flags (any)
if (s.effects & (EF_QUAD | EF_PENT)) {
    gi.dprintf("Has power-up\n");
}

// Check multiple flags (all)
if ((s.effects & (EF_QUAD | EF_PENT)) == (EF_QUAD | EF_PENT)) {
    gi.dprintf("Has both quad and pent\n");
}

Client-Side Rendering

The client uses these flags to control rendering:

// In client rendering code (clgame)
void CLG_AddEntity(centity_t *cent) {
    entity_t ent = {};
    
    // Check for rotation
    if (cent->current.effects & EF_ROTATE) {
        ent.angles[YAW] = anglemod(cl.time * 100);  // Rotate
    }
    
    // Check for animation
    if (cent->current.effects & EF_ANIM01) {
        int frame = (cl.time / 500) & 1;  // Alternate 0,1 at 2 Hz
        ent.frame = frame;
    }
    
    // Check for trails
    if (cent->current.effects & EF_GIB) {
        CLG_AddGibTrail(cent);  // Blood particles
    }
    
    // Check for power-up glows
    if (cent->current.effects & EF_QUAD) {
        CLG_AddQuadGlow(&ent);  // Blue glow
    }
    
    V_AddEntity(&ent);
}

Practical Examples

Bonus Item

void svg_item_bonus_t::Spawn() {
    // Rotating, animated item
    s.effects = EF_ROTATE | EF_ANIM_ALLFAST;
    s.entityType = ET_ITEM;
    gi.SetModel(edict, "models/items/bonus/tris.md2");
}

Result: Item spins and cycles through animation frames rapidly

Strobe Light

class svg_light_strobe_t : public svg_base_edict_t {
    void Spawn() override {
        s.effects = EF_ANIM01;
        SetThinkCallback(&svg_light_strobe_t::StrobeThink);
        nextThinkTime = level.time + FRAMETIME;
    }
    
    void StrobeThink() {
        // Toggle light on/off
        s.effects ^= EF_ANIM01;
        nextThinkTime = level.time + gametime_t::from_sec(0.1f);
    }
};

Result: Light blinks rapidly (10 Hz)

Power-Up Effects

void svg_player_edict_t::UpdatePowerUps() {
    // Clear old power-up flags
    s.effects &= ~(EF_QUAD | EF_PENT | EF_DOUBLE | EF_HALF_DAMAGE);
    
    // Apply active power-ups
    if (client->quad_framenum > level.frameNumber) {
        s.effects |= EF_QUAD;
    }
    if (client->invincible_framenum > level.frameNumber) {
        s.effects |= EF_PENT;
    }
    if (client->double_framenum > level.frameNumber) {
        s.effects |= EF_DOUBLE;
    }
}

Result: Player glows based on active power-ups

Blood Trail

void svg_monster_soldier_t::Die(/*...*/) {
    // Gib if overkill
    if (health < gib_health) {
        for (int i = 0; i < 4; i++) {
            auto *gib = ThrowGib("models/objects/gibs/sm_meat/tris.md2", damage);
            gib->s.effects |= EF_GIB;  // Blood trail
        }
    }
}

Result: Flying gibs leave blood particle trails

Teleporter Pad

void svg_misc_teleporter_t::Spawn() {
    s.effects = EF_TELEPORTER;
    s.modelindex = gi.modelindex("models/objects/dmspot/tris.md2");
    
    // Also play looping sound
    s.sound = gi.soundindex("world/amb10.wav");
}

Result: Pad has upward particle stream and ambient sound

Custom Effects Using Unused Flags

You can use unused flags for custom effects:

// Define custom flag
#define EF_CUSTOM_GLOW  EF_UNUSED_15

// Server-side
void svg_custom_entity_t::Spawn() {
    s.effects |= EF_CUSTOM_GLOW;
}

// Client-side (in clgame)
void CLG_AddEntity(centity_t *cent) {
    if (cent->current.effects & EF_CUSTOM_GLOW) {
        CLG_AddCustomGlowEffect(cent);  // Your custom rendering
    }
}

Note: Requires modifying both server and client code

Performance Considerations

Flag Overhead

Each flag set adds minimal overhead:

  • Flags are part of entity state (always sent)
  • Setting/clearing flags is bitwise operation (very fast)
  • Client-side checks are also bitwise (very fast)

Effect Complexity

Some effects are more expensive than others:

Low Cost:

  • EF_ROTATE - Simple angle calculation
  • EF_ANIM01 - Frame index calculation

Medium Cost:

  • EF_GIB - Spawns particles periodically
  • EF_TELEPORTER - Continuous particle spawning

High Cost:

  • EF_QUAD, EF_PENT - Additional rendering passes for glows
  • EF_COLOR_SHELL - Outline rendering

Tip: Don't combine too many expensive effects on many entities

Debugging

Console Commands

// Show entity effects
ent_info <entitynum>

// Output includes:
// Entity 5: monster_soldier
//   effects: EF_ROTATE | EF_GIB

Debug Visualization

#ifdef _DEBUG
void DebugEntityEffects(svg_base_edict_t *ent) {
    if (ent->s.effects & EF_ROTATE)
        gi.dprintf("  EF_ROTATE\n");
    if (ent->s.effects & EF_GIB)
        gi.dprintf("  EF_GIB\n");
    if (ent->s.effects & EF_QUAD)
        gi.dprintf("  EF_QUAD\n");
    // ... check all flags ...
}
#endif

Client-Side Debug

// In client game (clgame)
if (cl_show_effects->value) {
    DrawText(va("Effects: 0x%04X", cent->current.effects));
}

Common Mistakes

Forgetting to Set Model

// BAD: Effects without model
s.effects = EF_ROTATE;
// Nothing to rotate!

// GOOD: Set model first
gi.SetModel(edict, "models/items/health/tris.md2");
s.effects = EF_ROTATE;

Overwriting Instead of Adding

// BAD: Overwrites existing effects
s.effects = EF_QUAD;  // Loses EF_ROTATE if it was set

// GOOD: Add to existing effects
s.effects |= EF_QUAD;  // Preserves other flags

Wrong Animation Frames

// BAD: Model doesn't have enough frames
s.effects = EF_ANIM_ALL;  // But model only has 2 frames

// GOOD: Use appropriate animation
if (modelFrameCount <= 2) {
    s.effects = EF_ANIM01;  // Only use frames 0-1
}

Best Practices

Clear Before Setting

// When completely changing effect state
s.effects = 0;  // Clear all
s.effects = EF_ROTATE | EF_ANIM_ALL;  // Set new state

Use Constants for Clarity

// GOOD: Clear and maintainable
static constexpr uint32_t POWERUP_FLAGS = EF_QUAD | EF_PENT | EF_DOUBLE;

void ClearPowerUps() {
    s.effects &= ~POWERUP_FLAGS;
}

Document Custom Effects

// If using unused flags, document them
// EF_UNUSED_15: Custom entity glow effect
// EF_UNUSED_16: Custom pulsing effect
#define EF_CUSTOM_GLOW   EF_UNUSED_15
#define EF_CUSTOM_PULSE  EF_UNUSED_16

Related Documentation


See Also:

  • src/baseq2rtxp/sharedgame/sg_entity_flags.h - Flag definitions
  • src/baseq2rtxp/clgame/clg_entities.cpp - Client rendering code
  • src/baseq2rtxp/svgame/svg_spawn.cpp - Server entity spawning

Clone this wiki locally