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
|
--[[
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 function recalculate_base_attribute(being, attribute_name)
local old_base = being:base_attribute(attribute_name)
local new_base = old_base
if attribute == "Accuracy" then
-- Provisional
new_base = being:modified_attribute("Dexterity")
elseif attribute == "Defense" then
new_base = 0.3 * being:modified_attribute("Vitality")
elseif attribute == "Dodge" then
-- Provisional
new_base = being:modified_attribute("Agility")
elseif attribute == "M. dodge" then
-- TODO
new_base = 1
elseif attribute == "M. defense" then
-- TODO
new_base = 0
elseif attribute == "Bonus att. speed" then
-- TODO
new_base = 0
elseif attribute == "HP regeneration" then
local hp_per_sec = being:modified_attribute("Vitality") * 0.05
new_base = hp_per_sec * TICKS_PER_HP_REGENERATION / 10
elseif attribute == "HP" then
local hp = being:modified_attribute("HP")
local max_hp = being:modified_attribute("Max HP")
if hp > max_hp then
new_base = new_base - hp - max_hp
end
elseif attribute == "Max HP" then
local vit = being:modified_attribute("Vitality")
new_base = (vit + 3) * (vit + 20) * 0.125
elseif attribute == "Movement speed" then
-- Provisional
new_base = 3.0 + being:modified_attribute("Agility") * 0.08
elseif attribute == "Capacity" then
-- Provisional
new_base = 2000 + being:modified_attribute("Strength") * 180
elseif attribute == "Global ability cooldown" then
-- Provisional
new_base = 100 - being:modified_attribute("Willpower")
elseif attribute == "Level" then
-- Provisional
--new_base = 100 - 100 * math.pow(0.99999, being:base_attribute("XP"))
new_base = being:base_attribute("XP") / 20
end
if new_base ~= old_base then
being:set_base_attribute(attribute_name, new_base)
end
end
local function update_derived_attributes(being, attribute)
local attribute_name = attribute:name()
if attribute_name == "Strength" then
recalculate_base_attribute(being, "Capacity")
elseif attribute_name == "Agility" then
recalculate_base_attribute(being, "Dodge")
elseif attribute_name == "Vitality" then
recalculate_base_attribute(being, "Max HP")
recalculate_base_attribute(being, "HP regeneration")
recalculate_base_attribute(being, "Defense")
elseif attribute_name == "Intelligence" then
-- unimplemented
elseif attribute_name == "Willpower" then
recalculate_base_attribute(being, "Global ability cooldown")
elseif attribute_name == "XP" then
recalculate_base_attribute(being, "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("Level"))
end
function Entity:give_experience(experience)
local old_experience = self:base_attribute("XP")
local old_level = self:level()
self:set_base_attribute("XP", 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("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
|