Exemplo n.º 1
0
int StateControl_Raptor(struct entity_s *ent, struct ss_animation_s *ss_anim)
{
    character_command_p cmd = &ent->character->cmd;
    character_state_p state = &ent->character->state;
    uint16_t current_state = Anim_GetCurrentState(ss_anim);

    ent->character->rotate_speed_mult = 1.0f;
    ss_anim->anim_frame_flags = ANIM_NORMAL_CONTROL;

    state->sprint = 0x00;
    state->crouch = 0x00;
    state->attack = 0x00;

    switch(current_state)
    {
        case TR_STATE_RAPTOR_STAY: // -> 2 -> 3 -> 4 -> 6 -> 8
            if(state->dead)
            {
                Entity_SetAnimation(ent, ANIM_TYPE_BASE, TR_ANIMATION_RAPTOR_DEAD1, 0, NULL);
            }
            else if(cmd->action)
            {
                ss_anim->target_state = TR_STATE_RAPTOR_STAY_ATTACK;
            }
            else if(cmd->jump)
            {
                ss_anim->target_state = TR_STATE_RAPTOR_JUMP_ATTACK;
            }
            else if(cmd->move[0] < 0)
            {
                ss_anim->target_state = TR_STATE_RAPTOR_ARRRR;
            }
            else if(cmd->move[0] > 0)
            {
                ss_anim->target_state = (cmd->shift) ? (TR_STATE_RAPTOR_WALK) : (TR_STATE_RAPTOR_RUN);
            }
            else
            {
                ss_anim->target_state = TR_STATE_RAPTOR_STAY;
            }
            break;

        case TR_STATE_RAPTOR_WALK: // -> 1
            ent->dir_flag = ENT_MOVE_FORWARD;
            if(!state->dead && cmd->shift && (cmd->move[0] > 0))
            {
                ss_anim->target_state = TR_STATE_RAPTOR_WALK;
            }
            else
            {
                ss_anim->target_state = TR_STATE_RAPTOR_STAY;
            }
            break;

        case TR_STATE_RAPTOR_RUN: // -> 1 -> 7
            ent->dir_flag = ENT_MOVE_FORWARD;
            if(state->dead)
            {
                Entity_SetAnimation(ent, ANIM_TYPE_BASE, TR_ANIMATION_RAPTOR_DEAD2, 0, NULL);
            }
            else if(cmd->action)
            {
                ss_anim->target_state = TR_STATE_RAPTOR_RUN_ATTACK;
            }
            else if(!cmd->shift && (cmd->move[0] > 0))
            {
                ss_anim->target_state = TR_STATE_RAPTOR_RUN;
            }
            else
            {
                ss_anim->target_state = TR_STATE_RAPTOR_STAY;
            }
            break;

        case TR_STATE_RAPTOR_JUMP_ATTACK:
        case TR_STATE_RAPTOR_RUN_ATTACK:
        case TR_STATE_RAPTOR_STAY_ATTACK:
            state->attack = 0x01;
            break;
            
        case TR_STATE_RAPTOR_DEAD:
            state->dead = 0x02;
            break;
    };

    return 0;
}
Exemplo n.º 2
0
int StateControl_Wolf(struct entity_s *ent, struct ss_animation_s *ss_anim)
{
    character_command_p cmd = &ent->character->cmd;
    character_state_p state = &ent->character->state;
    uint16_t current_state = Anim_GetCurrentState(ss_anim);

    ent->character->rotate_speed_mult = 1.0f;
    ent->dir_flag = ENT_STAY;
    ss_anim->anim_frame_flags = ANIM_NORMAL_CONTROL;

    state->sprint = 0x00;
    state->crouch = 0x00;
    state->attack = 0x00;
    state->can_attack = 0x00;

    if(!state->dead && (ent->character->target_id != ENTITY_ID_NONE))
    {
        entity_p target = World_GetEntityByID(ent->character->target_id);
        if(target && Room_IsInNearRoomsList(ent->self->room, target->self->room))
        {
            float pos[3], *v = ent->bf->bone_tags[ent->character->bone_head].current_transform + 12;
            Mat4_vec3_mul_macro(pos, ent->transform.M4x4, v);
            pos[0] -= target->obb->centre[0];
            pos[1] -= target->obb->centre[1];
            pos[2] -= target->obb->centre[2];
            if((pos[2] > -target->obb->extent[2]) && (pos[2] < target->obb->extent[2]) &&
               (pos[0] * pos[0] + pos[1] * pos[1] < 400.0f * 400.0f))
            {
                state->can_attack = 0x01;
            }
        }
    }

    switch(current_state)
    {
        case TR_STATE_WOLF_STAY:// 1    // -> 2 -> 7 -> 8 -> 9
            cmd->rot[0] = 0;
            if(state->dead)
            {
                Entity_SetAnimation(ent, ANIM_TYPE_BASE, TR_ANIMATION_WOLF_DEAD1, 0, NULL);
            }
            else if(cmd->move[0] > 0)
            {
                ss_anim->target_state = TR_STATE_WOLF_WALK;
                ent->dir_flag = ENT_MOVE_FORWARD;
            }
            else if(cmd->shift)
            {
                ss_anim->target_state = TR_STATE_WOLF_STAY_CROUCH;
            }
            else if(cmd->action)
            {
                ss_anim->target_state = TR_STATE_WOLF_WOOOO;
            }
            else if(cmd->move[0] < 0)
            {
                ss_anim->target_state = TR_STATE_WOLF_IDLE;
            }
            else
            {
                ent->dir_flag = ENT_MOVE_FORWARD;
            }
            break;

        case TR_STATE_WOLF_STAY_CROUCH:// 9 // -> 1 -> 3 -> 5 -> 7 -> 12
            if(state->dead)
            {
                Entity_SetAnimation(ent, ANIM_TYPE_BASE, TR_ANIMATION_WOLF_DEAD1, 0, NULL);
            }
            else if(cmd->move[0] > 0)
            {
                ent->dir_flag = ENT_MOVE_FORWARD;
                ss_anim->target_state = (cmd->shift) ? (TR_STATE_WOLF_CROUCH) : (TR_STATE_WOLF_RUN);
            }
            else if(cmd->action)
            {
                cmd->rot[0] = 0;
                ss_anim->target_state = TR_STATE_WOLF_STAY_ATTACK;
            }
            else if(cmd->jump)
            {
                cmd->rot[0] = 0;
                ss_anim->target_state = TR_STATE_WOLF_WOOOO;
            }
            else if(cmd->shift)
            {
                ss_anim->target_state = TR_STATE_WOLF_STAY_CROUCH;
            }
            else
            {
                ent->dir_flag = ENT_MOVE_FORWARD;
                ss_anim->target_state = TR_STATE_WOLF_STAY;
            }
            break;

        case TR_STATE_WOLF_WALK:// 2    // -> 1 -> 5
            if(state->dead)
            {
                Entity_SetAnimation(ent, ANIM_TYPE_BASE, TR_ANIMATION_WOLF_DEAD1, 0, NULL);
            }
            else if(cmd->move[0] > 0)
            {
                ent->dir_flag = ENT_MOVE_FORWARD;
                ss_anim->target_state = (cmd->shift) ? (TR_STATE_WOLF_WALK) : (TR_STATE_WOLF_CROUCH);
            }
            else
            {
                ent->dir_flag = ENT_MOVE_FORWARD;
                ss_anim->target_state = TR_STATE_WOLF_STAY;
            }
            break;

        case TR_STATE_WOLF_RUN:// 3     // -> 6 -> 9 -> 10
            if(state->dead)
            {
                Entity_SetAnimation(ent, ANIM_TYPE_BASE, TR_ANIMATION_WOLF_DEAD1, 0, NULL);
            }
            else if(cmd->action)
            {
                ss_anim->target_state = TR_STATE_WOLF_JUMP_ATTACK;
            }
            else if(cmd->move[0] > 0)
            {
                ent->dir_flag = ENT_MOVE_FORWARD;
                ss_anim->target_state = (cmd->shift) ? (TR_STATE_WOLF_RUN) : (TR_STATE_WOLF_CROUCH);
            }
            else if(cmd->roll)
            {
                ent->dir_flag = ENT_MOVE_FORWARD;
                ss_anim->target_state = TR_STATE_WOLF_RUN_RIGHT;
            }
            else
            {
                ent->dir_flag = ENT_MOVE_FORWARD;
                ss_anim->target_state = TR_STATE_WOLF_STAY_CROUCH;
            }
            break;

        case TR_STATE_WOLF_CROUCH:// 5  // -> 3 -> 9 -> 12
            if(state->dead)
            {
                Entity_SetAnimation(ent, ANIM_TYPE_BASE, TR_ANIMATION_WOLF_DEAD1, 0, NULL);
            }
            else if(cmd->action)
            {
                cmd->rot[0] = 0;
                ent->dir_flag = ENT_MOVE_FORWARD;
                ss_anim->target_state = TR_STATE_WOLF_JUMP_ATTACK;
            }
            else if(cmd->move[0] > 0)
            {
                ent->dir_flag = ENT_MOVE_FORWARD;
                ss_anim->target_state = (cmd->shift) ? (TR_STATE_WOLF_CROUCH) : (TR_STATE_WOLF_RUN);
            }
            else
            {
                cmd->rot[0] = 0;
                ent->dir_flag = ENT_MOVE_FORWARD;
                ss_anim->target_state = TR_STATE_WOLF_STAY_CROUCH;
            }
            break;

        case TR_STATE_WOLF_STAY_ATTACK:// 12
            state->attack = 0x01;
            break;

        case TR_STATE_WOLF_JUMP_ATTACK:// 6   // -> 3
            ent->dir_flag = ENT_MOVE_FORWARD;
            state->attack = 0x01;
            if(state->dead)
            {
                Entity_SetAnimation(ent, ANIM_TYPE_BASE, TR_ANIMATION_WOLF_DEAD3, 0, NULL);
            }
            else if(cmd->action)
            {
                ss_anim->target_state = TR_STATE_WOLF_JUMP_ATTACK;
            }
            else
            {
                ss_anim->target_state = TR_STATE_WOLF_RUN;
            }
            break;

        case TR_STATE_WOLF_WOOOO:// 7
            cmd->rot[0] = 0;
            break;

        case TR_STATE_WOLF_IDLE:// 8    // -> 1
            cmd->rot[0] = 0;
            ent->no_move = 0x01;
            if(state->dead)
            {
                Entity_SetAnimation(ent, ANIM_TYPE_BASE, TR_ANIMATION_WOLF_DEAD1, 0, NULL);
            }
            else if(cmd->move[0] > 0)
            {
                ent->dir_flag = ENT_MOVE_FORWARD;
                ss_anim->target_state = TR_STATE_WOLF_STAY;
            }
            else
            {
                ss_anim->target_state = TR_STATE_WOLF_IDLE;
            }
            break;

        case TR_STATE_WOLF_RUN_RIGHT:// 10
            if(state->dead)
            {
                Entity_SetAnimation(ent, ANIM_TYPE_BASE, TR_ANIMATION_WOLF_DEAD2, 0, NULL);
            }
            else
            {
                cmd->rot[0] = -1;
                ent->dir_flag = ENT_MOVE_FORWARD;
            }
            break;

        case TR_STATE_WOLF_DEAD:// 11
            state->dead = 0x01;
            if(ss_anim->model->animations[ss_anim->current_animation].max_frame <= ss_anim->current_frame + 1)
            {
                state->dead = 0x02;
                state->ragdoll = 0x01;
            }
            break;

        default:
            cmd->rot[0] = 0;
            break;
    };

    return 0;
}
int StateControl_Crocodile(struct entity_s *ent, struct ss_animation_s *ss_anim)
{
    character_command_p cmd = &ent->character->cmd;
    character_state_p state = &ent->character->state;
    skeletal_model_p sm = ss_anim->model;
    uint16_t current_state = Anim_GetCurrentState(ss_anim);

    ent->character->rotate_speed_mult = 1.0f;
    ss_anim->anim_frame_flags = ANIM_NORMAL_CONTROL;

    state->sprint = 0x00;
    state->crouch = 0x00;
    state->attack = 0x00;

    switch(ent->move_type)
    {
        case MOVE_ON_WATER:
            ent->move_type = MOVE_UNDERWATER;
        case MOVE_UNDERWATER:
            sm = World_GetModelByID(TR_MODEL_CROCODILE_UW_TR1);
            if(sm && ss_anim->model->id != TR_MODEL_CROCODILE_UW_TR1)
            {
                ss_anim->model = sm;
                Anim_SetAnimation(ss_anim, TR_ANIMATION_CROCODILE_UW_FLOW, 0);
            }
            break;

        case MOVE_ON_FLOOR:
            sm = World_GetModelByID(TR_MODEL_CROCODILE_OF_TR1);
            if(sm && ss_anim->model->id != TR_MODEL_CROCODILE_OF_TR1)
            {
                ss_anim->model = sm;
                Anim_SetAnimation(ss_anim, TR_ANIMATION_CROCODILE_OF_STAY, 0);
            }
            break;
    }

    if(ss_anim->model->id == TR_MODEL_CROCODILE_UW_TR1)
    {
        ent->character->parameters.param[PARAM_AIR] = 1000;
        ent->character->parameters.maximum[PARAM_AIR] = 1000;

        switch(current_state)
        {
            case TR_STATE_CROCODILE_UW_FLOW: // -> 2
                if(state->dead)
                {
                    Entity_SetAnimation(ent, ANIM_TYPE_BASE, TR_ANIMATION_CROCODILE_UW_DEAD, 0, NULL);
                }
                else if(cmd->action)
                {
                    ss_anim->next_state = TR_STATE_CROCODILE_UW_ATTACK;
                }
                else
                {
                    ss_anim->next_state = TR_STATE_CROCODILE_UW_FLOW;
                }
                break;

            case TR_STATE_CROCODILE_UW_ATTACK: // -> 1
                state->attack = 0x01;
                ent->dir_flag = ENT_MOVE_FORWARD;
                if(!state->dead && cmd->action)
                {
                    ss_anim->next_state = TR_STATE_CROCODILE_UW_ATTACK;
                }
                else
                {
                    ss_anim->next_state = TR_STATE_CROCODILE_UW_FLOW;
                }
                break;
                
        case TR_STATE_CROCODILE_DEAD:
            state->dead = 0x02;
            break;
        };
    }
    else if(ss_anim->model->id == TR_MODEL_CROCODILE_OF_TR1)
    {
        switch(current_state)
        {
            case TR_STATE_CROCODILE_STAY: // -> 2 -> 3 -> 4 -> 5
                if(state->dead)
                {
                    Entity_SetAnimation(ent, ANIM_TYPE_BASE, TR_ANIMATION_CROCODILE_OF_DEAD, 0, NULL);
                }
                else if(cmd->action)
                {
                    ss_anim->next_state = TR_STATE_CROCODILE_ATTACK;
                }
                else if(cmd->move[0] > 0)
                {
                    ss_anim->next_state = (cmd->shift) ? (TR_STATE_CROCODILE_WALK) : (TR_STATE_CROCODILE_RUN);
                }
                else if(cmd->roll)
                {
                    ss_anim->next_state = TR_STATE_CROCODILE_RUN_RIGHT;
                }
                else
                {
                    ss_anim->next_state = TR_STATE_CROCODILE_STAY;
                }
                break;

            case TR_STATE_CROCODILE_WALK: // -> 1 -> 2
                ent->dir_flag = ENT_MOVE_FORWARD;
                if(!state->dead && (cmd->move[0] > 0))
                {
                    ss_anim->next_state = (cmd->shift) ? (TR_STATE_CROCODILE_WALK) : (TR_STATE_CROCODILE_RUN);
                }
                else
                {
                    ss_anim->next_state = TR_STATE_CROCODILE_STAY;
                }
                break;

            case TR_STATE_CROCODILE_RUN: // -> 1 -> 3
                ent->dir_flag = ENT_MOVE_FORWARD;
                if(!state->dead && (cmd->move[0] > 0))
                {
                    ss_anim->next_state = (cmd->shift) ? (TR_STATE_CROCODILE_WALK) : (TR_STATE_CROCODILE_RUN);
                }
                else
                {
                    ss_anim->next_state = TR_STATE_CROCODILE_STAY;
                }
                break;

            case TR_STATE_CROCODILE_RUN_RIGHT:
                ent->dir_flag = ENT_MOVE_FORWARD;
                cmd->rot[0] = -1;
                if(!state->dead && cmd->roll)
                {
                    ss_anim->next_state = TR_STATE_CROCODILE_RUN_RIGHT;
                }
                else
                {
                    ss_anim->next_state = TR_STATE_CROCODILE_WALK;
                }
                break;

            case TR_STATE_CROCODILE_ATTACK:
                state->attack = 0x01;
                break;
                
            case TR_STATE_CROCODILE_DEAD:
                state->dead = 0x02;
                break;
        };
    }

    return 0;
}
Exemplo n.º 4
0
///@TODO: move here TickEntity with Inversing entity state... see carefully heavy irregular cases
void Trigger_DoCommands(trigger_header_p trigger, struct entity_s *entity_activator)
{
    if(trigger && entity_activator)
    {
        bool has_non_continuos_triggers = false;

        for(trigger_command_p command = trigger->commands; command; command = command->next)
        {
            switch(command->function)
            {
            case TR_FD_TRIGFUNC_UWCURRENT:
                if(entity_activator->move_type == MOVE_ON_WATER)
                {
                    if(entity_activator->bf->animations.current_animation != TR_ANIMATION_LARA_ONWATER_DIVE_ALTERNATE)
                    {
                        Entity_SetAnimation(entity_activator, ANIM_TYPE_BASE, TR_ANIMATION_LARA_ONWATER_DIVE_ALTERNATE, 0);
                        entity_activator->move_type = MOVE_UNDERWATER;
                    }
                }
                else if(entity_activator->move_type == MOVE_UNDERWATER)
                {
                    Entity_MoveToSink(entity_activator, command->operands);
                }
                break;

            default:
                has_non_continuos_triggers = true;
                break;
            };
        }

        if(has_non_continuos_triggers)
        {
            int activator           = TR_ACTIVATOR_NORMAL;      // Activator is normal by default.
            int action_type         = TR_ACTIONTYPE_NORMAL;     // Action type is normal by default.
            int mask_mode           = TRIGGER_OP_OR;            // Activation mask by default.
            int activator_sector_status = Entity_GetSectorStatus(entity_activator);
            bool header_condition   = true;
            bool is_heavy           = false;
            // Activator type is LARA for all triggers except HEAVY ones, which are triggered by
            // some specific entity classes.
            // entity_activator_type  == TR_ACTIVATORTYPE_LARA and
            // trigger_activator_type == TR_ACTIVATORTYPE_MISC
            switch(trigger->sub_function)
            {
            case TR_FD_TRIGTYPE_HEAVY:
            case TR_FD_TRIGTYPE_HEAVYANTITRIGGER:
            case TR_FD_TRIGTYPE_HEAVYSWITCH:
                is_heavy = true;
                if((entity_activator->type_flags & ENTITY_TYPE_HEAVYTRIGGER_ACTIVATOR) == 0)
                {
                    return;
                }
                break;
            }

            switch(trigger->sub_function)
            {
            case TR_FD_TRIGTYPE_TRIGGER:
            case TR_FD_TRIGTYPE_HEAVY:
                activator = TR_ACTIVATOR_NORMAL;
                break;

            case TR_FD_TRIGTYPE_ANTIPAD:
                action_type = TR_ACTIONTYPE_ANTI;
            case TR_FD_TRIGTYPE_PAD:
                // Check move type for triggering entity.
                header_condition = (entity_activator->move_type == MOVE_ON_FLOOR);
                break;

            case TR_FD_TRIGTYPE_SWITCH:
                // Set activator and action type for now; conditions are linked with first item in operand chain.
                activator = TR_ACTIVATOR_SWITCH;
                action_type = TR_ACTIONTYPE_SWITCH;
                mask_mode = TRIGGER_OP_XOR;
                break;

            case TR_FD_TRIGTYPE_HEAVYSWITCH:
                // Action type remains normal, as HEAVYSWITCH acts as "heavy trigger" with activator mask filter.
                activator = TR_ACTIVATOR_SWITCH;
                mask_mode = TRIGGER_OP_XOR;
                break;

            case TR_FD_TRIGTYPE_KEY:
                // Action type remains normal, as key acts one-way (no need in switch routines).
                activator = TR_ACTIVATOR_KEY;
                break;

            case TR_FD_TRIGTYPE_PICKUP:
                // Action type remains normal, as pick-up acts one-way (no need in switch routines).
                activator = TR_ACTIVATOR_PICKUP;
                break;

            case TR_FD_TRIGTYPE_COMBAT:
                // Check weapon status for triggering entity.
                header_condition = header_condition && (entity_activator->character && (entity_activator->character->weapon_current_state > 0));
                break;

            case TR_FD_TRIGTYPE_DUMMY:
            case TR_FD_TRIGTYPE_SKELETON:   ///@FIXME: Find the meaning later!!!
                // These triggers are being parsed, but not added to trigger script!
                action_type = TR_ACTIONTYPE_BYPASS;
                break;

            case TR_FD_TRIGTYPE_ANTITRIGGER:
            case TR_FD_TRIGTYPE_HEAVYANTITRIGGER:
                action_type = TR_ACTIONTYPE_ANTI;
                break;

            case TR_FD_TRIGTYPE_MONKEY:
                header_condition = header_condition && (entity_activator->move_type == MOVE_MONKEYSWING);
                break;

            case TR_FD_TRIGTYPE_CLIMB:
                header_condition = header_condition && (entity_activator->move_type == MOVE_CLIMBING);
                break;

            case TR_FD_TRIGTYPE_TIGHTROPE:
                // Check state range for triggering entity.
                header_condition = header_condition && ((entity_activator->state_flags >= TR_STATE_LARA_TIGHTROPE_IDLE) && (entity_activator->state_flags <= TR_STATE_LARA_TIGHTROPE_EXIT));
                break;

            case TR_FD_TRIGTYPE_CRAWLDUCK:
                // Check state range for triggering entity.
                header_condition = header_condition && ((entity_activator->state_flags >= TR_ANIMATION_LARA_CROUCH_ROLL_FORWARD_BEGIN) && (entity_activator->state_flags <= TR_ANIMATION_LARA_CRAWL_SMASH_LEFT));
                break;
            }

            if(!header_condition)
            {
                return;
            }

            // Now execute operand chain for trigger function!
            bool first_command = true;
            int switch_sectorstatus = 0;
            int switch_event_state = -1;
            uint32_t switch_mask = 0;
            entity_p trig_entity = NULL;
            entity_p switch_entity = NULL;
            for(trigger_command_p command = trigger->commands; command; command = command->next)
            {
                switch(command->function)
                {
                case TR_FD_TRIGFUNC_OBJECT:         // ACTIVATE / DEACTIVATE object
                    trig_entity = World_GetEntityByID(command->operands);
                    // If activator is specified, first item operand counts as activator index (except
                    // heavy switch case, which is ordinary heavy trigger case with certain differences).
                    if(!trig_entity)
                    {
                        break;
                    }

                    if(first_command && (activator != TR_ACTIVATOR_NORMAL))
                    {
                        first_command = false;
                        switch(activator)
                        {
                        case TR_ACTIVATOR_SWITCH:
                            if(action_type == TR_ACTIONTYPE_SWITCH)
                            {
                                // Switch action type case.
                                switch_entity = trig_entity;
                                switch_event_state = (trig_entity->trigger_layout & ENTITY_TLAYOUT_EVENT) >> 5;
                                switch_sectorstatus = (trig_entity->trigger_layout & ENTITY_TLAYOUT_SSTATUS) >> 7;
                                switch_mask = (trig_entity->trigger_layout & ENTITY_TLAYOUT_MASK);
                                // Trigger activation mask is here filtered through activator's own mask.
                                switch_mask = (switch_mask == 0) ? (0x1F & trigger->mask) : (switch_mask & trigger->mask);

                                if((switch_event_state == 0) && (switch_sectorstatus == 1))
                                {
                                    Entity_SetSectorStatus(trig_entity, 0);
                                    trig_entity->timer = trigger->timer;
                                }
                                else if((switch_event_state == 1) && (switch_sectorstatus == 1))
                                {
                                    // Create statement for antitriggering a switch.
                                    Entity_SetSectorStatus(trig_entity, 0);
                                    trig_entity->timer = 0.0f;
                                }
                                else
                                {
                                    return;
                                }
                            }
                            else    /// end if (action_type == TR_ACTIONTYPE_SWITCH)
                            {
                                // Ordinary type case (e.g. heavy switch).
                                switch_sectorstatus = (entity_activator->trigger_layout & ENTITY_TLAYOUT_SSTATUS) >> 7;
                                switch_mask = (entity_activator->trigger_layout & ENTITY_TLAYOUT_MASK);
                                // Trigger activation mask is here filtered through activator's own mask.
                                switch_mask = (switch_mask == 0) ? (0x1F & trigger->mask) : (switch_mask & trigger->mask);

                                if(switch_sectorstatus == 0)
                                {
                                    int activation_state = Entity_Activate(trig_entity, entity_activator, switch_mask, mask_mode, trigger->once, trigger->timer);
                                    if(trigger->once && (activation_state != ENTITY_TRIGGERING_NOT_READY))
                                    {
                                        Entity_SetSectorStatus(entity_activator, 1);
                                        switch_sectorstatus = 1;
                                    }
                                }
                                else
                                {
                                    return;
                                }
                            }
                            break;

                        case TR_ACTIVATOR_KEY:
                            if((Entity_GetLock(trig_entity) == 1) && (Entity_GetSectorStatus(trig_entity) == 0))
                            {
                                Entity_SetSectorStatus(trig_entity, 1);
                            }
                            else
                            {
                                return;
                            }
                            break;

                        case TR_ACTIVATOR_PICKUP:
                            if(!(trig_entity->state_flags & ENTITY_STATE_ENABLED) && (Entity_GetSectorStatus(trig_entity) == 0))
                            {
                                Entity_SetSectorStatus(trig_entity, 1);
                            }
                            else
                            {
                                return;
                            }
                            break;
                        };
                    }
                    else
                    {
int StateControl_TorsoBoss(struct entity_s *ent, struct ss_animation_s *ss_anim)
{
    character_command_p cmd = &ent->character->cmd;
    character_state_p state = &ent->character->state;
    uint16_t current_state = Anim_GetCurrentState(ss_anim);

    ent->character->rotate_speed_mult = 1.0f;
    ss_anim->anim_frame_flags = ANIM_NORMAL_CONTROL;

    state->sprint = 0x00;
    state->crouch = 0x00;
    state->attack = 0x00;

    ent->character->rotate_speed_mult = 0.33;
    switch(current_state)
    {
        case TR_STATE_TORSO_BOSS_STAY: // -> 2 -> 3 -> 4 -> 5 -> 6 -> 7
            cmd->rot[0] = 0;
            ent->dir_flag = ENT_MOVE_FORWARD;
            if(state->dead)
            {
                Entity_SetAnimation(ent, ANIM_TYPE_BASE, TR_ANIMATION_TORSO_BOSS_DEAD, 0, NULL);
            }
            else if(cmd->action)
            {
                ss_anim->target_state = (cmd->shift) ? (TR_STATE_TORSO_BOSS_ATTACK_BIG) : (TR_STATE_TORSO_BOSS_ATTACK);
            }
            else if(cmd->jump)
            {
                ss_anim->target_state = TR_STATE_TORSO_BOSS_ATTACK_KILL;
            }
            else if(cmd->move[1] < 0)
            {
                ss_anim->target_state = TR_STATE_TORSO_BOSS_TURN_RIGHT;
            }
            else if(cmd->move[1] > 0)
            {
                ss_anim->target_state = TR_STATE_TORSO_BOSS_TURN_LEFT;
            }
            else if(cmd->move[0] > 0)
            {
                ss_anim->target_state = TR_STATE_TORSO_BOSS_MOVE;
            }
            else
            {
                ss_anim->target_state = TR_STATE_TORSO_BOSS_STAY;
            }
            break;

        case TR_STATE_TORSO_BOSS_MOVE: // -> 1
            if(!state->dead && (cmd->move[1] > 0))
            {
                ss_anim->target_state = TR_STATE_TORSO_BOSS_MOVE;
            }
            else
            {
                ss_anim->target_state = TR_STATE_TORSO_BOSS_STAY;
            }
            break;

        case TR_STATE_TORSO_BOSS_TURN_RIGHT: // -> 1
            cmd->rot[0] = 1;
            if(!state->dead && (cmd->move[1] < 0))
            {
                ss_anim->target_state = TR_STATE_TORSO_BOSS_TURN_RIGHT;
            }
            else
            {
                ss_anim->target_state = TR_STATE_TORSO_BOSS_STAY;
            }
            break;

        case TR_STATE_TORSO_BOSS_TURN_LEFT: // -> 1
            cmd->rot[0] = -1;
            if(!state->dead && (cmd->move[1] > 0))
            {
                ss_anim->target_state = TR_STATE_TORSO_BOSS_TURN_LEFT;
            }
            else
            {
                ss_anim->target_state = TR_STATE_TORSO_BOSS_STAY;
            }
            break;

        case TR_STATE_TORSO_BOSS_ATTACK_KILL:
        case TR_STATE_TORSO_BOSS_ATTACK:
        case TR_STATE_TORSO_BOSS_ATTACK_BIG:
        case TR_STATE_TORSO_BOSS_ATTACK_JUMP:
            state->attack = 0x01;
            cmd->rot[0] = 0;
            break;

        case TR_STATE_TORSO_BOSS_DEAD:
            state->dead = 0x02;
            break;
            
        default:
            cmd->rot[0] = 0;
            break;
    };

    return 0;
}