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
|