summaryrefslogtreecommitdiff
path: root/src/map/skill-pools.cpp
blob: 78d3f3408b07a57bce7d44fb82181ef96de4005c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include "skill.hpp"

#include "../common/cxxstdio.hpp"

#include "battle.hpp"
#include "pc.hpp"

#include "../poison.hpp"

SkillID skill_pool_skills[MAX_POOL_SKILLS];
int skill_pool_skills_size = 0;

void skill_pool_register(SkillID id)
{
    if (skill_pool_skills_size + 1 >= MAX_POOL_SKILLS)
    {
        FPRINTF(stderr,
                 "Too many pool skills! Increase MAX_POOL_SKILLS and recompile.");
        return;
    }

    skill_pool_skills[skill_pool_skills_size++] = id;
}

int skill_pool(struct map_session_data *sd, SkillID *skills)
{
    int i, count = 0;

    for (i = 0; count < MAX_SKILL_POOL && i < skill_pool_skills_size; i++)
    {
        SkillID skill_id = skill_pool_skills[i];
        if (bool(sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED))
        {
            if (skills)
                skills[count] = skill_id;
            ++count;
        }
    }

    return count;
}

int skill_pool_size(struct map_session_data *sd)
{
    return skill_pool(sd, NULL);
}

int skill_pool_max(struct map_session_data *sd)
{
    return sd->status.skill[TMW_SKILLPOOL].lv;
}

int skill_pool_activate(struct map_session_data *sd, SkillID skill_id)
{
    if (bool(sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED))
        return 0;               // Already there
    else if (sd->status.skill[skill_id].id == skill_id  // knows the skill
             && (skill_pool_size(sd) < skill_pool_max(sd)))
    {
        sd->status.skill[skill_id].flags |= SKILL_POOL_ACTIVATED;
        pc_calcstatus(sd, 0);
        MAP_LOG_PC(sd, "SKILL-ACTIVATE %d %d %d",
                uint16_t(skill_id), sd->status.skill[skill_id].lv,
                skill_power(sd, skill_id));
        return 0;
    }

    return 1;                   // failed
}

bool skill_pool_is_activated(struct map_session_data *sd, SkillID skill_id)
{
    return bool(sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED);
}

int skill_pool_deactivate(struct map_session_data *sd, SkillID skill_id)
{
    if (bool(sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED))
    {
        sd->status.skill[skill_id].flags &= ~SKILL_POOL_ACTIVATED;
        MAP_LOG_PC(sd, "SKILL-DEACTIVATE %d", uint16_t(skill_id));
        pc_calcstatus(sd, 0);
        return 0;
    }

    return 1;
}

// Yields the stat associated with a skill.
// Returns zero if none, or SP_STR, SP_VIT, ... otherwise
static
SP skill_stat(SkillID skill_id)
{
    return skill_db[skill_id].stat;
}

int skill_power(struct map_session_data *sd, SkillID skill_id)
{
    SP stat = skill_stat(skill_id);
    int stat_value, skill_value;
    int result;

    if (stat == SP::ZERO || !skill_pool_is_activated(sd, skill_id))
        return 0;

    stat_value = battle_get_stat(stat, &(sd->bl));
    skill_value = sd->status.skill[skill_id].lv;

    if ((skill_value * 10) - 1 > stat_value)
        skill_value += (stat_value / 10);
    else
        skill_value *= 2;

    result = (skill_value * stat_value) / 10;

    return result;
}

int skill_power_bl(struct block_list *bl, SkillID skill)
{
    if (bl->type == BL_PC)
        return skill_power((struct map_session_data *) bl, skill);
    else
        return 0;
}