summaryrefslogtreecommitdiff
path: root/example/scripts/attributes.lua
blob: 3e9b97e09108da8d4a45603593e4979df07b6bf4 (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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
--[[

 This file demonstrates how attributes are getting calculated and how they can
 be linked to each other.

 See http://doc.manasource.org/attributes.xml for more info.

--]]

local ATTR_EXP = 22
local ATTR_LEVEL = 23

local function recalculate_base_attribute(being, attribute)
    local old_base = being:base_attribute(attribute)
    local new_base = old_base
    if attribute == ATTR_ACCURACY then
        -- Provisional
        new_base = being:modified_attribute(ATTR_DEX)
    elseif attribute == ATTR_DEFENSE then
        new_base = 0.3 * being:modified_attribute(ATTR_VIT)
    elseif attribute == ATTR_DODGE then
        -- Provisional
        new_base = being:modified_attribute(ATTR_AGI)
    elseif attribute == ATTR_MAGIC_DODGE then
        -- TODO
        new_base = 1
    elseif attribute == ATTR_MAGIC_DEFENSE then
        -- TODO
        new_base = 0
    elseif attribute == ATTR_BONUS_ASPD then
        -- TODO
        new_base = 0
    elseif attribute == ATTR_HP_REGEN then
        local hp_per_sec = being:modified_attribute(ATTR_VIT) * 0.05
        new_base = hp_per_sec * TICKS_PER_HP_REGENERATION / 10
    elseif attribute == ATTR_HP then
        local hp = being:modified_attribute(ATTR_HP)
        local max_hp = being:modified_attribute(ATTR_MAX_HP)

        if hp > max_hp then
            new_base = new_base - hp - max_hp
        end
    elseif attribute == ATTR_MAX_HP then
        local vit = being:modified_attribute(ATTR_VIT)
        new_base = (vit + 3) * (vit + 20) * 0.125
    elseif attribute == ATTR_MOVE_SPEED_TPS then
        -- Provisional
        new_base = 3.0 + being:modified_attribute(ATTR_AGI) * 0.08
    elseif attribute == ATTR_INV_CAPACITY then
        -- Provisional
        new_base = 2000 + being:modified_attribute(ATTR_STR) * 180
    elseif attribute == ATTR_ABILITY_COOLDOWN then
        -- Provisional
        new_base = 100 - being:modified_attribute(ATTR_WIL)
    elseif attribute == ATTR_LEVEL then
        -- Provisional
        --new_base = 100 - 100 * math.pow(0.99999, being:base_attribute(ATTR_EXP))
        new_base = being:base_attribute(ATTR_EXP) / 20
    end

    if new_base ~= old_base then
        being:set_base_attribute(attribute, new_base)
    end

end

local function update_derived_attributes(being, attribute)
    if attribute == ATTR_STR then
        recalculate_base_attribute(being, ATTR_INV_CAPACITY)
    elseif attribute == ATTR_AGI then
        recalculate_base_attribute(being, ATTR_DODGE)
    elseif attribute == ATTR_VIT then
        recalculate_base_attribute(being, ATTR_MAX_HP)
        recalculate_base_attribute(being, ATTR_HP_REGEN)
        recalculate_base_attribute(being, ATTR_DEFENSE)
    elseif attribute == ATTR_INT then
        -- unimplemented
    elseif attribute == ATTR_WIL then
        recalculate_base_attribute(being, ATTR_ABILITY_COOLDOWN)
    elseif attribute == ATTR_EXP then
        recalculate_base_attribute(being, ATTR_LEVEL)
    end
end

on_recalculate_base_attribute(recalculate_base_attribute)
on_update_derived_attribute(update_derived_attributes)

function Entity:level()
    return math.floor(self:base_attribute(ATTR_LEVEL))
end

function Entity:give_experience(experience)
    local old_experience = self:base_attribute(ATTR_EXP)
    local old_level = self:level()
    self:set_base_attribute(ATTR_EXP, old_experience + experience)
    if self:level() > old_level then
        self:say("LEVELUP!!! " .. self:level())
        self:set_attribute_points(self:attribute_points() + 1)
        self:set_correction_points(self:correction_points() + 1)
    end
end

local mobs_config = require "scripts/monster/settings"

local exp_receiver = {}

-- Give EXP for monster kills
local function monster_damaged(mob, source, damage)

    local receiver = exp_receiver[mob] or { chars = {}, total = 0 }
    exp_receiver[mob] = receiver

    if source and source:type() == TYPE_CHARACTER then
        mob:change_anger(source, damage)

        local current_damage = receiver.chars[source]
        if not current_damage then
            on_remove(source, function(removed_being)
                receiver[removed_being] = nil
            end)
            on_death(source, function(removed_being)
                receiver[removed_being] = nil
            end)
        end

        current_damage = (current_damage or 0) + damage
        receiver.chars[source] = current_damage
        receiver.total = receiver.total + damage
    end

    if mob:base_attribute(ATTR_HP) == 0 then
        local mob_config = mobs_config[mob:name()]
        local experience = mob_config.experience or 0
        for char, damage in pairs(receiver.chars) do
            local gained_exp = damage / receiver.total * experience
            char:give_experience(gained_exp)
        end
    end
end

for _, monsterclass in pairs(get_monster_classes()) do
    monsterclass:on_damaged(monster_damaged)
end