• <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>

            天行健 君子當(dāng)自強而不息

            Controlling Players and Characters(39)

            Once characters take enough damage, they die, and when that happens, the following
            function is called:

            void cCharController::death(sCharacter* attacker, sCharacter* victim)
            {
                
            // if a PC or NPC dies, then do not remove from list.
                if(victim->type == CHAR_PC || victim->type == CHAR_NPC)
                {        
                    victim->update_enable = 
            false;

                    
            if(victim->type == CHAR_PC)
                        pc_death(victim);
                    
            else
                        npc_death(victim);
                }
                
            else    // victim->type = CHAR_MONSTER
                {
                    
            // give attacker the victim's experience
                    if(attacker && gain_exp(attacker, victim->char_def.exp))
                    {
                        
            char text[128];
                        sprintf(text, "+%lu exp.", victim->char_def.exp);
                        set_char_msg(attacker, text, 500, COLOR_WHITE);
                    }
                }

                
            if(m_mil && victim->char_def.money)
                    drop_money(victim->pos_x, victim->pos_y, victim->pos_z, victim->char_def.money);

                
            if(rand()%100 < victim->char_def.drop_chance)
                    drop_item(victim->pos_x, victim->pos_y, victim->pos_z, victim->char_def.drop_item);

                sMeshAnim& mesh_anim = m_mesh_anim[victim->char_def.mesh_index];

                
            if(--mesh_anim.count == 0)
                {
                    mesh_anim.mesh.free();
                    mesh_anim.anim.free();
                }

                
            // remove the dead character from list

                
            if(victim->prev)
                    victim->prev->next = victim->next;
                
            else
                    m_root_char = victim->next;

                
            if(victim->next)
                    victim->next->prev = victim->prev;

                victim->prev = victim->next = NULL;
                delete victim;
            }

            virtual void pc_death(sCharacter* character)
            {        

             }

            virtual void npc_death(sCharacter* character)
            {        
            }


            Taking the pointer to the victim, the controller is able to handle its death appropriately.
            If the victim is a monster, you use the attacking character pointer to apply the
            experience points. Also, if a monster dies, the death function determines how much
            gold the monster drops and what item (if any) is dropped and calls the appropriate
            controller function to handle such dropped items.

            Leading into the next function, whenever a PC kills a monster, that PC gains the
            experience stored in the monster’s MCL definition. To apply the experience, use
            the following function:

                virtual bool gain_exp(sCharacter* character, long amount)
                {
                    character->char_def.exp += amount;

                    
            return true;
                }

            Notice that the gain_exp function can be overridden. This can occur when you’re
            using a separate battle sequence engine; you don’t want experience added to the
            PC until the battle is over. Consequently, you use your own function to keep track
            of how much experience to apply when the battle is over.

            The overridden function can also occur when the character needs to go up in
            experience levels once he gains a certain number of experience points. The
            gan_exp function is the place to determine just when a character goes up an
            experience level and to take the appropriate actions to increase their abilities.

            One note about the gain_exp function: The character controller normally displays
            the number of experience points that a PC gains when killing a monster. To stop
            the controller from displaying this number (as in the case of the separate battle
            sequences), return a value of false from the Experience function.

            The next couple of functions are the ones responsible for processing attacks and
            spells. Both functions take pointers to the attacking characters (if any) as well as
            their intended victims. For spells, a sSpellTracker structure is required to tell the
            controller which spell to process, as well as the sSpell structure that contains the
            information about the spell effects to use:

            bool cCharController::attack(sCharacter* attacker, sCharacter* victim)
            {
                
            if(attacker == NULL || victim == NULL)
                    
            return false;

                
            // do not attack dead or hurt character
                if(victim->action == CHAR_DIE || victim->action == CHAR_HURT)
                    
            return false;

                victim->attacker = attacker;
                attacker->victim = victim;
                
                
            // return if hit missed
                if(rand()%1000 > get_to_hit(attacker))
                {
                    set_char_msg(victim, "Missed!", 500, COLOR_WHITE);
                    
            return false;
                }

                
            // return if hit dodged
                if(rand()%1000 <= get_agility(victim))
                {
                    set_char_msg(victim, "Dodged!", 500, COLOR_WHITE);
                    
            return false;
                }

                
            // if character is asleep, randomly wake them up (50% chance).
                if((victim->ailments & AILMENT_SLEEP) && rand()%100 < 50)    
                    victim->ailments &= ~AILMENT_SLEEP;    

                
            // attack landed, apply damage.
                damage(victim, true, get_attack(attacker), -1, -1);

                
            return true;
            }

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

            bool cCharController::spell(sCharacter* caster, const sSpellTracker* spell_tracker, const sSpell* spells)
            {
                
            if(caster == NULL || spell_tracker == NULL || spells == NULL)
                    
            return false;

                
            const sSpell* spell_ptr = &spells[spell_tracker->spell_index];

                
            // reduce magic
                caster->mana_points -= spell_ptr->cost;
                
            if(caster->mana_points < 0)
                    caster->mana_points = 0;

                
            // can not cast if silenced
                if(caster->ailments & AILMENT_SILENCED)
                {
                    set_char_msg(caster, "Silenced!", 500, COLOR_WHITE);
                    
            return false;
                }

                
            // handle self-targeting spells instantly
                if(spell_ptr->target == TARGET_SELF)
                {
                    spell_effect(caster, caster, spell_ptr);
                    
            return true;
                }

                
            float spell_dist = spell_ptr->range * spell_ptr->range;

                sCharacter* closest_char = NULL;
                
            float closest = 0.0f;

                
            // scan through all characters and look for hits
                for(sCharacter* char_ptr = m_root_char; char_ptr != NULL; char_ptr = char_ptr->next)
                {
                    
            // only bother with characters of allowed types.
                    // also, allow a RAISE_DEAD PC spell to affect any character.

                    
            bool allow = false;

                    
            if(char_ptr != caster && spell_tracker->affect_type == char_ptr->type)
                        allow = 
            true;

                    
            if(char_ptr->type == CHAR_PC && spell_ptr->effect == RAISE_DEAD)
                        allow = 
            true;

                    
            if(!allow)
                        
            continue;

                    
            // get distance from target to character
                    float x_diff = fabs(char_ptr->pos_x - spell_tracker->target_x);
                    
            float y_diff = fabs(char_ptr->pos_y - spell_tracker->target_y);
                    
            float z_diff = fabs(char_ptr->pos_z - spell_tracker->target_z);

                    
            // get x/z and y distances
                    float xz_dist = (x_diff * x_diff + z_diff * z_diff) - spell_dist;
                    
            float y_dist  = (y_diff * y_diff) - spell_dist;

                    
            // get target x/z and y radius
                    float min_x, min_y, min_z, max_x, max_y, max_z;
                    char_ptr->
            object.get_bounds(&min_x, &min_y, &min_z, &max_x, &max_y, &max_z, NULL);

                    
            float xz_radius = max(max_x - min_x, max_z - min_z) * 0.5f;
                    
            float y_radius  = (max_y - min_y) * 0.5f;

                    
            // check if character in range
                    if(xz_dist > (xz_radius * xz_radius) || y_dist > (y_radius * y_radius))
                        
            continue;

                    
            // determine what to do if in range
                    if(spell_ptr->target == TARGET_SINGLE)
                    {
                        
            // record closest character in range
                        float dist = x_diff * x_diff + y_diff * y_diff + z_diff * z_diff;

                        
            if(closest_char == NULL || dist < closest)
                        {
                            closest_char = char_ptr;
                            closest = dist;
                        }           
                    }
                    
            else    // spell hit area targets
                        spell_effect(caster, char_ptr, spell_ptr);
                }

                
            // process spell on closest character if needed
                if(spell_ptr->target == TARGET_SINGLE && closest_char)
                    spell_effect(caster, closest_char, spell_ptr);

                
            return true;
            }

            Each of the preceding functions takes into account the attacking and defending
            characters’ abilities and adjust their values accordingly. When an attack connects,
            damage is dealt. When a spell is found to have affected the target (remember,
            there’s a chance it might fail), the next function is called to process the effects:
            bool cCharController::spell_effect(sCharacter* caster, sCharacter* target, const sSpell* spell)
            {
                
            if(target == NULL || spell == NULL)
                    
            return false;

                
            long chance;

                
            // calculate chance of hitting
                if(caster)
                {
                    
            // a spell always lands if target == caster
                    if(caster == target)
                        chance = 100;
                    
            else
                        chance = (get_mental(caster)/100.0f + 1.0f) * spell->chance;        
                }
                
            else
                    chance = spell->chance;

                
            // alter chance by target's registance
                if(caster != target)
                    chance *= (1.0f - get_resistance(target)/100.0f);

                
            // see if spell failed
                if(rand()%100 > chance)
                {
                    set_char_msg(target, "Failed!", 500, COLOR_WHITE);
                    
            return false;
                }
                
                
            bool can_hit = true;    // flag character to allow effect

                
            if(target->action == CHAR_HURT || target->action == CHAR_DIE)
                    can_hit = 
            false;

                
            // store attacker and victim

                target->attacker = caster;
              
                
            if(caster)
                    caster->victim = target;

                
            char text[64];

                
            // process spell effect
                switch(spell->effect)
                {
                
            case ALTER_HEALTH:
                    
            if(can_hit)
                    {
                        
            if(spell->value[0] < 0.0f)      // apply damage
                            damage(target, false, -spell->value[0], spell->damage_class, spell->cure_class);
                        
            else if(spell->value[0] > 0.0f) // cure damage
                        {
                            target->health_points += spell->value[0];

                            
            if(target->health_points > target->char_def.health_points)
                                target->health_points = target->char_def.health_points;

                            
            // display amount healed
                            sprintf(text, "+%lu HP", spell->value[0]);
                            set_char_msg(target, text, 500, D3DCOLOR_RGBA(0, 64, 255, 255));
                        }            
                    }

                    
            break;

                
            case ALTER_MANA:
                    
            if(can_hit)
                    {
                        target->mana_points += spell->value[0];

                        
            if(target->mana_points < 0)
                            target->mana_points = 0;
                        
            else if(target->mana_points > target->char_def.mana_points)
                            target->mana_points = target->char_def.mana_points;

                        
            if(spell->value[0] < 0.0f)
                            sprintf(text, "%ld MP", spell->value[0]);
                        
            else if(spell->value[0] > 0.0f)
                            sprintf(text, "+%ld MP", spell->value[0]);

                        set_char_msg(target, text, 500, D3DCOLOR_RGBA(0, 128, 64, 255));            
                    }

                    
            break;

                
            case CURE_AILMENT:
                    
            if(can_hit)
                    {
                        
            // cure ailment and display message
                        target->ailments &= ~(long)spell->value[0];
                        set_char_msg(target, "Cure", 500, COLOR_WHITE);            
                    }

                    
            break;

                
            case CAUSE_AILMENT:
                    
            if(can_hit)
                    {
                        
            // cause ailment and display message
                        target->ailments |= (long)spell->value[0];
                        set_char_msg(target, "Ailment", 500, COLOR_WHITE);            
                    }

                    
            break;

                
            case RAISE_DEAD:
                    
            if(target->action == CHAR_DIE)
                    {
                        target->health_points = 1;
                        target->mana_points   = 0;
                        target->action        = CHAR_DIE;
                        target->is_lock       = 
            false;
                        target->action_timer  = 0;
                        target->ailments      = 0;
                        target->update_enable = 
            true;
                    }
                        
                    
            break;

                
            case INSTANT_KILL:
                    
            if(can_hit)
                        set_char_action(target, CHAR_DIE, 0);

                    
            break;

                
            case DISPEL_MAGIC:
                    
            if(can_hit)
                        target->ailments = 0;

                    
            break;

                
            case TELEPORT:      // teleport PC/NPC/MONSTER
                    if(can_hit)
                    {
                        
            if(target->type == CHAR_PC)
                            pc_teleport(caster, spell);
                        
            else
                        {
                            target->pos_x = spell->value[0];
                            target->pos_y = spell->value[1];
                            target->pos_z = spell->value[2];
                        }
                    }

                    
            break;
                }

                
            return true;
            }
             

            posted on 2007-12-04 19:45 lovedday 閱讀(275) 評論(0)  編輯 收藏 引用


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


            公告

            導(dǎo)航

            統(tǒng)計

            常用鏈接

            隨筆分類(178)

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

            搜索

            最新評論

            无遮挡粉嫩小泬久久久久久久| 久久久久久国产精品美女| 伊人热热久久原色播放www| 人妻少妇久久中文字幕| 国产三级精品久久| 麻豆亚洲AV永久无码精品久久| 色综合色天天久久婷婷基地| 久久天天躁夜夜躁狠狠| 欧美综合天天夜夜久久| 久久久www免费人成精品| 18岁日韩内射颜射午夜久久成人| 久久亚洲国产精品五月天婷| 成人妇女免费播放久久久| 四虎影视久久久免费观看| 91精品日韩人妻无码久久不卡| 少妇久久久久久被弄高潮| 久久精品一区二区影院| 精品久久一区二区| 99久久国产精品免费一区二区| 久久久久亚洲AV无码去区首| 久久国产高清字幕中文| 久久久久久无码Av成人影院 | 久久亚洲AV成人无码电影| 国内精品久久久久久久久| 久久精品国产亚洲综合色| 欧洲精品久久久av无码电影| 久久影视综合亚洲| 久久电影网| 久久精品免费网站网| 国产69精品久久久久99| 国产精品久久久天天影视| 久久国产精品无码一区二区三区| 久久精品国产2020| 浪潮AV色综合久久天堂| 久久精品国产99国产精品亚洲| 久久精品国产亚洲αv忘忧草| 久久久久国产精品三级网| 亚洲精品高清一二区久久| 一级a性色生活片久久无| 亚洲va久久久噜噜噜久久男同| 久久久久波多野结衣高潮|