天行健 君子当自强而不息

Controlling Players and Characters(38)

Coming up is a huge collection of functions you use to retrieve and set the specific
information about a character (related to the artificial intelligence functionality or
actions):

    cCharIcs* get_char_ics(long id)
    {
        sCharacter* character;

        
if((character = get_char(id)) == NULL)
            
return NULL;

        
return character->char_ics;
    }

    
void set_char_lock(long id, bool is_lock)
    {
        sCharacter* character;

        
if((character = get_char(id)) != NULL)
            character->is_lock = is_lock;
    }

    
void set_char_lock_timer(long id, long action_timer)
    {
        sCharacter* character;

        
if((character = get_char(id)) != NULL)            
            character->action_timer = action_timer;
    }

    
void set_char_type(long id, long type)
    {
        sCharacter* character;

        
if((character = get_char(id)) != NULL)
            character->type = type;
    }

    
long get_char_type(long id)
    {
        sCharacter* character;

        
if((character = get_char(id)) == NULL)
            
return 0;

        
return character->type;
    }

    
void set_char_ai(long id, long ai)
    {
        sCharacter* character;

        
if((character = get_char(id)) != NULL)
            character->ai = ai;
    }

    
long get_char_ai(long id)
    {
        sCharacter* character;

        
if((character = get_char(id)) == NULL)
            
return 0;

        
return character->ai;
    }

    
void set_char_distance(long id, float dist)
    {
        
// set evade/follow distance

        sCharacter* character;

        
if((character = get_char(id)) != NULL)
            character->distance = dist;
    }

    
float get_char_distance(long id)
    {
        
// get evade/follow distance

        sCharacter* character;

        
if((character = get_char(id)) == NULL)
            
return 0.0f;

        
return character->distance;
    }

    
void set_char_route(long id, long num_points, const sRoutePoint* route)
    {
        sCharacter* character;
        
if((character = get_char(id)) == NULL)
            
return;

        
// free old route
        delete[] character->route;
        character->route = NULL;

        
// set new route
        if((character->num_points = num_points) != 0)
        {
            character->route = 
new sRoutePoint[num_points];
            memcpy(character->route, route, num_points * 
sizeof(sRoutePoint));

            character->cur_point = 0;
        }
    }

    
void set_char_script(long id, const char* script_filename)
    {
        sCharacter* character;
        
        
if((character = get_char(id)) != NULL)
            strcpy(character->script_filename, script_filename);
    }

    
char* get_char_script(long id)
    {
        sCharacter* character;
        
if((character = get_char(id)) == NULL)
            
return NULL;

        
return character->script_filename;
    }

    
void set_update_enable(long id, bool update_enable)
    {
        sCharacter* character;

        
if((character = get_char(id)) != NULL)
            character->update_enable = update_enable;
    }

    
bool get_update_enable(long id)
    {
        sCharacter* character;

        
if((character = get_char(id)) == NULL)
            
return false;

        
return character->update_enable;
    }

    
void move_char(long id, float pos_x, float pos_y, float pos_z)
    {
        sCharacter* character;

        
if((character = get_char(id)) != NULL)
        {
            character->pos_x = pos_x;
            character->pos_y = pos_y;
            character->pos_z = pos_z;
        }
    }

    
void get_char_position(long id, float* pos_x, float* pos_y, float* pos_z)
    {
        sCharacter* character;

        
if((character = get_char(id)) != NULL)
        {
            
if(pos_x)   *pos_x = character->pos_x;
            
if(pos_y)   *pos_y = character->pos_y;
            
if(pos_z)   *pos_z = character->pos_z;
        }
    }

    
void set_char_bound(long id,
                        
float min_x, float min_y, float min_z,
                        
float max_x, float max_y, float max_z)
    {
        sCharacter* character;

        
if((character = get_char(id)) != NULL)
        {
            character->min_x = min(min_x, max_x);
            character->min_y = min(min_y, max_y);
            character->min_z = min(min_z, max_z);
            character->max_x = max(min_x, max_x);
            character->max_y = max(min_y, max_y);
            character->max_z = max(min_z, max_z);
        }
    }

    
void get_char_bound(long id,
                        
float* min_x, float* min_y, float* min_z,
                        
float* max_x, float* max_y, float* max_z)
    {
        sCharacter* character;

        
if((character = get_char(id)) != NULL)
        {
            
if(min_x)   *min_x = character->min_x;
            
if(min_y)   *min_y = character->min_y;
            
if(min_z)   *min_z = character->min_z;
            
if(max_x)   *max_x = character->max_x;
            
if(max_y)   *max_y = character->max_y;
            
if(max_z)   *max_z = character->max_z;
        }
    }

    
void set_target_char(long id, long target_id)
    {
        sCharacter* character;
        
if((character = get_char(id)) == NULL)
            
return;

        
if(target_id == -1)
            character->target_char = NULL;
        
else
        {
            sCharacter* target_char;

            
for(target_char = m_root_char; target_char != NULL; target_char = target_char->next)
            {
                
if(target_char->id == target_id)
                {
                    character->target_char = target_char;
                    
break;
                }
            }

            
// clear target if not found in list
            if(target_char == NULL)
                character->target_char = NULL;
        }
    }

    
void set_char_action(sCharacter* character, long action, long action_timer)
    {
        
if(character == NULL)
            
return;

        
// make sure attack, spell, and item supporting charge.
        if(action == CHAR_ATTACK || action == CHAR_SPELL || action == CHAR_ITEM)
        {
            
if(character->charge < 100.0f)
                
return;
        }

        character->action = action;
        play_action_sound(character);

        
long mesh_index = character->char_def.mesh_index;

        
// set action timer
        if(action_timer == -1)
            character->action_timer = 1;
        
else
        {
            
ulong anim_length = m_mesh_anim[mesh_index].anim.get_time_length(m_char_anim[action].name);
            character->action_timer = action_timer + anim_length * 30;
        }
    }

Skipping the details on the preceding functions, you now encounter the function
used to set up the data that displays a message over a character:


    void set_char_msg(sCharacter* character, const char* msg, long msg_timer, D3DCOLOR msg_color)
    {
        
// set text messages to float up from character

        strcpy(character->msg, msg);

        character->msg_timer = msg_timer;
        character->msg_color = msg_color;
    }

set_char_msg allows you to temporarily overlay a string of text for Timer milliseconds, drawing
the text in the color specified. You set a character message to inform the player of
an event, such as how many health points were reduced because of an attack.

Coming next is the function that processes the damage taken from an attack,
whether it’s physical or magical (as denoted by the
is_physical_attack flag, set to true for
physical attacks or false for magical):

void cCharController::damage(sCharacter* victim,
                             
bool is_physical_attack, long attack_amount,
                             
long damage_class, long cure_class)
{
    
// can not attack if already dead or being hurt or not update enabled
    if(victim == NULL || !victim->update_enable || victim->action == CHAR_DIE || victim->action == CHAR_HURT)
        
return;

    
float   range;
    
long    damage_amount;
    
    
if(is_physical_attack)  // adjust for defense if physical attack
    {
        
// random value for less/more damage (-+10%)
        range = (rand()%20 + 90.0f) / 100.0f;
        damage_amount = attack_amount * range;

        
// subtract for defencse to victim (allow -20% difference)
        range = (rand()%20 + 80.0f) / 100.0f;
        damage_amount -= (get_defense(victim) * range);
    }
    
else    // adjust for magical attack            
        damage_amount = attack_amount * (1.0f - get_resistance(victim)/100.0f);    

    
if(damage_amount < 0)   // bounds check
        damage_amount = 0;

    
// check for double damage
    if(victim->char_def.class_index == damage_class)
        damage_amount *= 2;

    
// check for cure damage
    if(victim->char_def.class_index == cure_class)
        damage_amount = -labs(damage_amount) / 2;

    
// if no physical damage is dealt then randomly deal 10-20% of damage from the original amount.
    if(damage_amount == 0 && is_physical_attack)
    {
        range = (rand()%10 + 10) / 100.0f;
        damage_amount = attack_amount * range;
    }
    
    victim->health_points -= damage_amount;

    
char text[128];

    
if(damage_amount > 0)       // set hurt status and display message
    {
        sprintf(text, "-%lu HP", damage_amount);
        set_char_msg(victim, text, 500, D3DCOLOR_RGBA(255, 64, 0, 255));

        
// only set hurt if idle or moving
        if(victim->action == CHAR_MOVE || victim->action == CHAR_IDLE)
            set_char_action(victim, CHAR_HURT, 0);
    }
    
else if(damage_amount < 0)  // display cure amount
    {
        sprintf(text, "+%lu HP", -damage_amount);
        set_char_msg(victim, text, 500, D3DCOLOR_RGBA(0, 64, 255, 255));
    }    
}

Damage takes a pointer to the character taking damage, the type of damage (physical
or magical), the amount of damage to apply, and the double damage and cure
classes of the attack. You adjust the damage amount based on the defense and resistance
abilities of the victim.

posted on 2007-12-04 19:19 lovedday 阅读(267) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论