• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天行健 君子當自強而不息

            Controlling Players and Characters(33)

            The next two functions to come along work in conjunction with the update functionality
            of the class. At every frame that a character needs updating, a specific
            function is called to update the character’s actions. This specific function is dependent
            on the type of character being updated; for PCs, that specific function is
            pc_update (which is overridden by you in order to control your player).

            virtual void pc_update(sCharacter* character, long elaspsed,
                                   float* x_move, float* y_move, float* z_move)
            {
            }

            For NPCs and monsters, the update function called is npc_monster_update. pc_update does
            nothing at this point because you need to write the code in the main application
            to control the player. Monsters and NPCs already have their AIs sets, and the controller
            knows how to handle them with npc_monster_update.

            ///////////////////////////////////////////////////////////////////////////////////////////////////

            static bool char_can_spell_health(const sCharacter* character, const sSpell* spell, int spell_index)
            {
                
            return spell->name[0] && spell->effect == ALTER_HEALTH && spell->value[0] > 0.0f &&
                       character->mana_points >= spell->cost &&
                       (character->char_def.magic_spell[spell_index / 32] & (1 << (spell_index & 31)));
            }

            static bool char_can_spell_dispel(const sCharacter* character, const sSpell* spell, int spell_index)
            {
                
            return spell->name[0] && spell->effect == DISPEL_MAGIC && character->mana_points >= spell->cost &&
                       (character->char_def.magic_spell[spell_index / 32] & (1 << (spell_index & 31)));
            }

            static bool char_can_spell_ailment(const sCharacter* character, const sSpell* spell, int spell_index)
            {
                
            return spell->name[0] && spell->effect == CAUSE_AILMENT && character->mana_points >= spell->cost &&
                       (character->char_def.magic_spell[spell_index / 32] & (1 << (spell_index & 31)));
            }

            static bool char_can_spell(const sCharacter* character, const sSpell* spell, int spell_index)
            {
                
            return spell->name[0] && character->mana_points >= spell->cost &&
                       (character->char_def.magic_spell[spell_index / 32] & (1 << (spell_index & 31)));
            }

            static bool is_char_ailment(const sCharacter* character)
            {
                
            return character->ailments & AILMENT_POISON ||
                       character->ailments & AILMENT_SLEEP ||             
                       character->ailments & AILMENT_PARALYZE ||          
                       character->ailments & AILMENT_ENCHANTED ||         
                       character->ailments & AILMENT_DUMBFOUNDED ||       
                       character->ailments & AILMENT_SLOW ||              
                       character->ailments & AILMENT_BLIND ||             
                       character->ailments & AILMENT_SILENCED;
            }

            static bool is_enhanced_ailment(long ailment)
            {
                
            return ailment & AILMENT_STRONG ||      
                       ailment & AILMENT_BARRIER ||     
                       ailment & AILMENT_SUREFOOTED ||  
                       ailment & AILMENT_FAST ||        
                       ailment & AILMENT_HAWKEYE;
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////////
             
            void cCharController::npc_monster_update(sCharacter* character, long elapsed,
                                                     
            float* x_move, float* y_move, float* z_move)
            {
                
            if(character == NULL)
                    
            return;

                
            float move_x, move_y, move_z;
                move_x = move_y = move_z = 0.0f;

                
            float x_diff, y_diff, z_diff, dist, radius;

                
            float speed = elapsed/1000.0f * get_speed(character);

                
            // move character based on their type
                switch(character->ai)
                {
                
            case CHAR_STAND:
                    
            break;

                
            case CHAR_WANDER:
                    
            // calculate new distance and direction if needed

                    character->distance -= elapsed;

                    
            if(character->distance <= 0.0f)
                    {
                        character->distance  = rand()%2000 + 2000.0f;
                        character->direction = (rand()%360) * 0.01744444f;
                    }

                    
            // process walk or stand still
                    if(character->distance > 1000.0f)
                    {
                        move_x = sin(character->direction) * speed;
                        move_z = cos(character->direction) * speed;

                        character->action = CHAR_MOVE;
                    }
                    
            else
                    {
                        
            // stand still for one second
                        character->action = CHAR_IDLE;
                    }

                    
            break;

                
            case CHAR_ROUTE:
                  {
                    sRoutePoint* route = &character->route[character->cur_point];

                    
            // determine if character has reached point

                    x_diff = fabs(character->pos_x - route->pos_x);
                    y_diff = fabs(character->pos_y - route->pos_y);
                    z_diff = fabs(character->pos_z - route->pos_z);

                    dist = x_diff * x_diff + y_diff * y_diff + z_diff * z_diff;
                    radius = get_xz_radius(character) * 0.25f;

                    
            // goto next point if reached
                    if(dist < (radius * radius))
                    {
                        
            if(++character->cur_point >= character->num_points)
                            character->cur_point = 0;

                        route = &character->route[character->cur_point];

                        
            // calculate new differences and distance 

                        x_diff = fabs(character->pos_x - route->pos_x);
                        y_diff = fabs(character->pos_y - route->pos_y);
                        z_diff = fabs(character->pos_z - route->pos_z);

                        dist = x_diff * x_diff + y_diff * y_diff + z_diff * z_diff;
                    }

                    
            // setup movement towards target
                    dist = sqrt(dist);

                    
            if(speed > dist)
                        speed = dist;

                    move_x = (route->pos_x - character->pos_x) / dist * speed;
                    move_z = (route->pos_z - character->pos_z) / dist * speed;

                    character->direction = atan2(move_x, move_z);
                    character->action    = CHAR_MOVE;

                    
            break;
                  }

                
            case CHAR_FOLLOW:    
                    
            // check distance between characters

                    x_diff = fabs(character->pos_x - character->target_char->pos_x);
                    y_diff = fabs(character->pos_y - character->target_char->pos_y);
                    z_diff = fabs(character->pos_z - character->target_char->pos_z);

                    dist = x_diff * x_diff + y_diff * y_diff + z_diff * z_diff;

                    
            // update if further than target
                    if(dist > (character->distance * character->distance))
                    {
                        
            // setup movement towards target
                        dist = sqrt(dist);

                        
            if(speed > dist)
                            speed = dist;

                        move_x = (character->target_char->pos_x - character->pos_x) / dist * speed;
                        move_z = (character->target_char->pos_z - character->pos_z) / dist * speed;
                        
                        character->direction = atan2(move_x, move_z);
                        character->action    = CHAR_MOVE;
                    }

                    
            break;

                
            case CHAR_EVADE:
                    
            // check distance between characters

                    x_diff = fabs(character->pos_x - character->target_char->pos_x);
                    y_diff = fabs(character->pos_y - character->target_char->pos_y);
                    z_diff = fabs(character->pos_z - character->target_char->pos_z);

                    dist = x_diff * x_diff + y_diff * y_diff + z_diff * z_diff;

                    
            // update if closer than distance
                    if(dist < (character->distance * character->distance))
                    {
                        
            // setup movement away from target
                        dist = sqrt(dist);

                        
            if(speed > dist)
                            speed = dist;

                        move_x = -(character->target_char->pos_x - character->pos_x) / dist * speed;
                        move_z = -(character->target_char->pos_z - character->pos_z) / dist * speed;

                        character->direction = atan2(move_x, move_z);
                        character->action = CHAR_MOVE;
                    }

                    
            break;
                }

                sCharacter* char_ptr;

                
            // process monster actions if at full charge
                if(character->type == CHAR_MONSTER && character->charge >= 100.0f)
                {
                    
            // determine chance of attacking
                    if(rand()%100 <= character->char_def.to_attack)
                    {
                        
            // scan through list and pick a character
                        for(char_ptr = m_root_char; char_ptr != NULL; char_ptr = char_ptr->next)
                        {
                            
            // randomly pick update enabled PC, and make sure the target is not hurt or dead.
                            if(char_ptr != character && char_ptr->type == CHAR_PC && char_ptr->update_enable &&
                               char_ptr->action != CHAR_DIE && char_ptr->action != CHAR_HURT && rand()%100 < 50)
                            {
                                
            // get distance to target
                                x_diff = fabs(character->pos_x - char_ptr->pos_x);
                                y_diff = fabs(character->pos_y - char_ptr->pos_y);
                                z_diff = fabs(character->pos_z - char_ptr->pos_z);

                                dist = x_diff * x_diff + y_diff * y_diff + z_diff * z_diff;

                                
            // make sure in range to attack                    
                                radius = get_xz_radius(character) + character->char_def.attack_range;

                                
            // attack only in range
                                if((radius * radius) >= dist)
                                {                        
                                    character->victim  = char_ptr;
                                    char_ptr->attacker = character;

                                    
            // clear movement
                                    move_x = move_y = move_z = 0.0f;

                                    
            // point towards target character
                                    x_diff = char_ptr->pos_x - character->pos_x;
                                    z_diff = char_ptr->pos_z - character->pos_z;
                                    character->direction = atan2(x_diff, z_diff);

                                    set_char_action(character, CHAR_ATTACK, 0);
                                    
            break;
                                }
                            }
                        }
                    }   
                    
            else if(rand()%100 <= character->char_def.to_magic)
                    {
                        
            // determine chance of spell casting

                        
            bool is_spell_cast = false;
                        
            long spell_index;

                        
            // if health is less than half, then there is 50% chance of healing (if monster knows any heal spells).
                        if(character->health_points <= character->char_def.health_points / 2)
                        {
                            
            // search for a known heal spell
                            for(long i = 0; i < NUM_SPELL_DEF; i++)
                            {
                                
            // this is the spell, determine chance to heal.
                                if(char_can_spell_health(character, &m_msl[i], i) && rand()%100 < 50)
                                {                        
                                    character->victim      = character;
                                    character->attacker    = character;
                                    character->spell_index = i;
                                    character->target_type = CHAR_MONSTER;                     
                                    character->target_x    = character->pos_x;
                                    character->target_y    = character->pos_y;
                                    character->target_z    = character->pos_z;

                                    
            // clear movement
                                    move_x = move_y = move_z = 0.0f;
                                   
                                    set_char_action(character, CHAR_SPELL, 0);
                                    is_spell_cast = 
            true;
                                    
            break;
                                }
                            }
                        }

                        
            // if there are bad status ailments, then there is 50% chance of dispeling magic.
                        if(is_char_ailment(character) && !is_spell_cast)
                        {
                            
            // search for a known dispell spell
                            for(long i = 0; i < NUM_SPELL_DEF; i++)
                            {
                                
            // this is the spell, determine chance to dispel.
                                if(char_can_spell_dispel(character, &m_msl[i], i) && rand()%100 < 50)
                                {                        
                                    character->victim      = character;
                                    character->attacker    = character;
                                    character->spell_index = i;
                                    character->target_type = CHAR_MONSTER;                     
                                    character->target_x    = character->pos_x;
                                    character->target_y    = character->pos_y;
                                    character->target_z    = character->pos_z;

                                    
            // clear movement
                                    move_x = move_y = move_z = 0.0f;
                                   
                                    set_char_action(character, CHAR_SPELL, 0);
                                    is_spell_cast = 
            true;
                                    
            break;
                                }
                            }
                        }

                        
            // if no spells already cast, then pick a random spell to attack with.
                        if(!is_spell_cast)
                        {
                            spell_index = rand() % NUM_SPELL_DEF;

                            
            // scan through list until a spell is found that monster can cast.
                            for(long i = 0; i < NUM_SPELL_DEF; i++)
                            {
                                
            if(char_can_spell(character, &m_msl[spell_index], spell_index) && rand()%100 < 50)
                                {
                                    
            // scan through list and pick a character
                                    for(char_ptr = m_root_char; char_ptr != NULL; char_ptr = char_ptr->next)
                                    {
                                        
            // randomly pick an update enabled PC, and make sure the target is not hurt or dead.
                                        // also, do not cast self-targeting spells here.
                                        if(char_ptr != character && m_msl[spell_index].target != TARGET_SELF &&
                                            char_ptr->type == CHAR_PC && char_ptr->update_enable &&
                                            char_ptr->action != CHAR_DIE && char_ptr->action != CHAR_HURT &&
                                            rand()%100 < 50)
                                        {
                                            
            float y1, y2;

                                            
            // get heights of attacker and target for line of sight checking
                                            character->object.get_bounds(NULL, NULL, NULL, NULL, &y1, NULL, NULL);
                                            y1 = (y1 * 0.5f) + character->pos_y;

                                            char_ptr->
            object.get_bounds(NULL, NULL, NULL, NULL, &y2, NULL, NULL);
                                            y2 = (y2 * 0.5f) + char_ptr->pos_y;

                                            
            // get distance to target

                                            x_diff = fabs(character->pos_x - char_ptr->pos_x);
                                            y_diff = fabs(character->pos_y - char_ptr->pos_y);
                                            z_diff = fabs(character->pos_z - char_ptr->pos_z);
                            
                                            dist = x_diff * x_diff + y_diff * y_diff + z_diff * z_diff;
                                            dist = sqrt(dist) - get_xz_radius(char_ptr);
                                           
                                            
            bool in_line_sight = line_of_sight(character, char_ptr,
                                                                               character->pos_x, y1, character->pos_z,
                                                                               char_ptr->pos_x, y2, char_ptr->pos_z);

                                            
            // make sure target is in range and in line sight
                                            if(in_line_sight && dist <= m_msl[spell_index].max_dist)
                                            {
                                                character->victim      = char_ptr;
                                                char_ptr->attacker     = character;
                                                character->spell_index = spell_index;
                                                character->target_type = CHAR_PC;
                                                character->target_x    = char_ptr->pos_x;
                                                character->target_y    = char_ptr->pos_y;
                                                character->target_z    = char_ptr->pos_z;

                                                
            // face toward target (only if not self)
                                                x_diff = char_ptr->pos_x - character->pos_x;
                                                z_diff = char_ptr->pos_z - character->pos_z;

                                                character->direction = atan2(x_diff, z_diff);

                                                move_x = move_y = move_z = 0.0f;    
            // clear movement

                                                set_char_action(character, CHAR_SPELL, 0);
                                                is_spell_cast = 
            true;
                                                
            break;
                                            }
                                        }
                                    }

                                    
            break;
                                }

                                
            // go to next spelll
                                spell_index = (spell_index + 1) % NUM_SPELL_DEF;
                            }
                        }

                        
            // if still no spell cast, try casting a known self-enhancing ailment-effecting spell.
                        if(!is_spell_cast)
                        {
                            
            for(long i = 0; i < NUM_SPELL_DEF; i++)
                            {
                                
            // make sure it is self-enhancing
                                if(char_can_spell_ailment(character, &m_msl[i], i) && is_enhanced_ailment(m_msl[i].value[0]) &&
                                   rand()%100 < 10)
                                {
                                    
            // make sure ailment not already set
                                    if(!(character->ailments & (long)m_msl[i].value[0]))
                                    {
                                        character->victim      = character;
                                        character->attacker    = character;
                                        character->spell_index = i;
                                        character->target_type = CHAR_MONSTER;
                                        character->target_x    = character->pos_x;
                                        character->target_y    = character->pos_y;
                                        character->target_z    = character->pos_z;

                                        move_x = move_y = move_z = 0.0f;    
            // clear movement

                                        set_char_action(character, CHAR_SPELL, 0);
                                        
            break;
                                    }
                                }
                            }
                        }
                    }
                }

                
            // store movement
                *x_move = move_x;
                *y_move = move_y;
                *z_move = move_z;
            }

            The steps taken for initiating an update and processing all of a character’s actions
            is a long one. First, you iterate each character in the list of active characters. The
            appropriate character’s update function is called (pc_update or npc_monster_update).

            posted on 2007-12-04 16:29 lovedday 閱讀(301) 評論(0)  編輯 收藏 引用


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            公告

            導(dǎo)航

            統(tǒng)計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關(guān)鏈接

            搜索

            最新評論

            国产精品久久网| 久久久久久午夜成人影院| 亚洲AV无码久久| 久久久亚洲裙底偷窥综合| 午夜视频久久久久一区 | 91久久精品无码一区二区毛片| 亚洲AV无码一区东京热久久| 亚洲国产日韩综合久久精品| 久久精品中文字幕一区| 久久青青草原精品国产不卡| 久久亚洲天堂| 区久久AAA片69亚洲| 日韩av无码久久精品免费| 亚洲va久久久噜噜噜久久狠狠| 久久精品亚洲一区二区三区浴池| 国产午夜精品久久久久免费视| 91久久婷婷国产综合精品青草| 亚洲国产成人久久精品动漫| 久久天天躁狠狠躁夜夜2020老熟妇 | 亚洲中文字幕伊人久久无码| 亚洲熟妇无码另类久久久| 996久久国产精品线观看| 99久久综合国产精品二区| 亚洲国产成人久久综合野外| 18岁日韩内射颜射午夜久久成人| 久久久久99精品成人片试看| 亚洲精品国产成人99久久| 久久久久亚洲国产| 99re久久精品国产首页2020| 日韩电影久久久被窝网| 久久婷婷五月综合色高清| 久久久久一级精品亚洲国产成人综合AV区| 久久综合精品国产一区二区三区| 亚洲精品无码久久一线| 国产成人无码精品久久久久免费| 伊人久久综合无码成人网| 97久久精品人人做人人爽| 无码人妻少妇久久中文字幕蜜桃| 成人a毛片久久免费播放| 久久综合给久久狠狠97色| 深夜久久AAAAA级毛片免费看|