Date: 2015/03/04 05:32:17 UTC-08:00
Type: Denizen Script
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# Procedural mob spawning/summoning (pms)
pmsMainWrapper:
type: world
events:
on server start:
- flag global pmsWorldName:Kratanien
- flag global pmsMaxDifficulty:100
- flag global pmsMobHP:!
- flag global pmsMobHP:|:10|200
- flag global pmsMobSpeed:!
- flag global pmsMobSpeed:|:0.23|0.4
- flag global pmsAttackDamage:!
- flag global pmsAttackDamage:|:1.5|7
- flag global pmsKnockbackResistance:!
- flag global pmsKnockbackResistance:|:-0.5|1
# TODO add gaussRand for difficulty
- flag global pmsPlayerHeadProbability:!
- flag global pmsPlayerHeadProbability:|:0|0.3
# The probability of each location to spawn a normal mob. Bosses will always spawn.
# E.g: You provide 10 locations to spawnTreasureMobs. Each of the normal mobs will have this probability of spawning.
# This logic helps to randomize the spawn locations, thus players cannot anticipate where the mobs will spawn.
- flag global pmsSpawnProbability:0.66
# Doesn't work correctly right now because Minecraft ties the durability of an item
# to the DropChance. If DropChance is between 0 and 1, it will automatically generate
# a random durability for the dropped item, regardless of the actual setting.
# If however the DropChance is > 1, the durability will be the set number, but the item will always drop.
# I'm leaving this in as it might chance in the future (now is: Minecraft 1.8.1, 03.02.2015)
- flag global pmsItemDamaged:!
- flag global pmsItemDamaged:|:0.2|0.9
- flag global pmsDropRate:!
- flag global pmsDropRate:|:0.2|0.05
# Normal mobs will have 0.5 * boss difficulty
- flag global pmsMobToBossDifficulty:0.5
- flag global pmsBabyPercentage:!
- flag global pmsBabyPercentage:|:0.3|-1
# Mobs with min level will have 10% (=0.1) chance of having an item equipped.
# Mobs with max level will have 90% (=0.9) chance of having an item equipped.
- flag global pmsEquipRange:!
- flag global pmsEquipRange:|:0.3|1
# In percent. E.g.: 0 = Five players have same difficulty as one player.
# 15 = Difficulty is 130% for three players (adding 15% difficulty per additional player)
# One player will always have difficulty 100% scaled to <fl@pmsMaxDifficulty>
- flag global pmsDifficultyIncreasePerPlayer:15
- flag global pmsWeapons:!
- flag global pmsWeapons:|:sword_1|sword_2|sword_3|sword_4|sword_5|sword_6|sword_7|sword_8|sword_9|sword_10|sword_11|sword_12|sword_13|sword_14|sword_15
- flag global pmsBows:!
- flag global pmsBows:|:bow_1|bow_2|bow_3|bow_4|bow_5|bow_6
- flag global pmsHelmets:!
- flag global pmsHelmets:|:helmet_1|helmet_2|helmet_3|helmet_4|helmet_5|helmet_6|helmet_7|helmet_8|helmet_9|helmet_10|helmet_11|helmet_12|helmet_13|helmet_14|helmet_15|helmet_16|helmet_17
- flag global pmsChestplates:!
- flag global pmsChestplates:|:chestplate_1|chestplate_2|chestplate_3|chestplate_4|chestplate_5|chestplate_6|chestplate_7|chestplate_8|chestplate_9|chestplate_10|chestplate_11|chestplate_12|chestplate_13|chestplate_14|chestplate_15
- flag global pmsLeggings:!
- flag global pmsLeggings:|:leggings_1|leggings_2|leggings_3|leggings_4|leggings_5|leggings_6|leggings_7|leggings_8|leggings_9|leggings_10|leggings_11|leggings_12
- flag global pmsBoots:!
- flag global pmsBoots:|:boots_1|boots_2|boots_3|boots_4|boots_5|boots_6|boots_7|boots_8|boots_9|boots_10|boots_11|boots_12
getProceduralMob:
type: procedure
definitions: difficulty|isBoss
script:
- define hp <proc[randomMobHP].context[<def[difficulty]>|<def[isBoss]>]>
- define speed <proc[lerp].context[pmsMobSpeed|<def[difficulty]>|<def[isBoss]>]>
- define attackDamage <proc[lerp].context[pmsAttackDamage|<def[difficulty]>|<def[isBoss]>]>
- define knockbackResistance <proc[lerp].context[pmsKnockbackResistance|<def[difficulty]>|<def[isBoss]>]>
#- narrate "HP: <def[hp]> Dmg: <def[attackDamage]> Spd: <def[speed]> KnockBackRes: <def[knockbackResistance]>"
#- define randomMobs li@witch|creeper|zombie|skeleton|endermite|silverfish|blaze
#- determine e@<def[randomMobs].random>[<def[defaultAttributes]>]
# Take a random player who has ever played on the server and set his face to the boss
- if <def[isBoss]> && <util.random.decimal.is[OR_LESS].than[<proc[lerp].context[pmsPlayerHeadProbability|<def[difficulty]>|<def[isBoss]>]>]> {
- define skull ";skull=<server.list_players.random.name>"
}
- if <util.random.decimal.is[OR_LESS].than[<proc[lerp].context[pmsBabyPercentage|<def[difficulty]>|<def[isBoss]>]>]> {
- define isBaby ";age=baby"
}
# TODO knockbackresistence as parameter
- define defaultAttributes max_health=<def[hp]><tern[<def[skull].exists>]:<def[skull]>||>;health=<def[hp]>;movementSpeed=<def[speed]>;attackDamage=<def[attackDamage]>;followRange=64;knockbackResistance=<def[knockbackResistance]>
- if <def[isBoss].exists> && <def[isBoss].is[==].to[true]> {
- define bossAttributes custom_name=<proc[myrandomBossName].context[<def[difficulty]>]>;%defaultAttributes%
- random {
# TODO ;villager=true
#- determine e@ghast[custom_name=<proc[myrandomBossName]>;<def[defaultAttributes]>]
- determine e@skeleton[%bossAttributes%;skeleton=WITHER]
- determine e@pig_zombie[%bossAttributes%]
- determine e@zombie[%bossAttributes%]
}
}
else {
- define defaultAttributes "custom_name=<gray>Lv <def[difficulty].mul[<fl@pmsMobToBossDifficulty>].round>;%defaultAttributes%"
- random {
- determine e@witch[<def[defaultAttributes]>]
- determine e@creeper[<def[defaultAttributes]>]
- determine e@creeper[powered=true;<def[defaultAttributes]>]
# TODO ;jockey=true
#- determine e@endermite[<def[defaultAttributes]>]
#- determine e@silverfish[<def[defaultAttributes]>]
- determine e@blaze[<def[defaultAttributes]>]
- determine e@zombie[<def[defaultAttributes]><tern[<def[isBaby].exists>]:<def[isBaby]>||>]
- determine e@pig_zombie[<def[defaultAttributes]><tern[<def[isBaby].exists>]:<def[isBaby]>||>]
- determine e@skeleton[<def[defaultAttributes]>]
#- determine e@rabbit[color=KILLER;<def[defaultAttributes]>]
}
}
randomMobHP:
type: procedure
definitions: difficulty|isBoss
script:
- define mobHP <proc[lerp].context[pmsMobHP|<def[difficulty]>|<def[isBoss]>]>
- determine <proc[gaussRand].context[<def[mobHP]>|1|<fl@pmsMobHP.get[2]>].round>
gaussRand:
type: procedure
# TODO implement sigma as percentage
definitions: myinput|min|max
script:
- define returnValue <math:<util.random.gauss>*(%myinput%/16)+%myinput%>
- if <def[min].exists> && <def[max].exists> {
- if <el@val[%returnValue%].is[LESS].than[<el@val[%min%]>]> {
- define returnValue %min%
}
else if <el@val[%returnValue%].is[MORE].than[<el@val[%max%]>]> {
- define returnValue %max%
}
}
- determine %returnValue%
randomitem:
type: procedure
definitions: globalflagname|difficulty|isBoss
script:
- define itemlist <fl@%globalflagname%.as_list>
- if !<def[isBoss].exists> || <def[isBoss].is[==].to[false]> {
# Normal mob's item level will be 1/2 of the boss item level
- define difficulty <def[difficulty].mul[<fl@pmsMobToBossDifficulty>].round>
}
- define itemlevel <proc[lerpIndex].context[%globalflagname%|%difficulty%]>
# weigh generated item levels closer to max level. E.g: difficulty 50/100 -> most itemlevels will be in range 30-50
# E.g. Boss with level 50 will get item 5 (if 10 items in list).
- define myrand <util.random.int[<util.random.int[0].to[<def[itemlevel]>]>].to[<def[itemlevel]>]>
- determine <def[itemlist].get[%myrand%]>
# Linear interpolation
lerp:
type: procedure
# passing the list directly always only passed the first item from the list, thus globalflagname
definitions: globalflagname|difficulty|isBoss
script:
- if !<def[difficulty].exists> {
- announce to_console "PMS: Difficulty not specified, assuming 50%."
- define difficulty <fl@pmsMaxDifficulty.div[2]>
}
- if !<def[isBoss].exists> || <def[isBoss].is[==].to[false]> {
- define difficulty <def[difficulty].mul[<fl@pmsMobToBossDifficulty>].round>
}
- define valuelist <fl@%globalflagname%.as_list>
- if <def[valuelist].exists> && <el@val[<def[valuelist].size>].is[MORE].than[1]> {
# 0.6 - 0.2 = 0.4
- define rangeDelta <math:<def[valuelist].get[2]>-<def[valuelist].get[1]>>
# 60/100 * 0.4 = 0,24 -> 0,24+0,2 = 0,44 -> calculated 60% from 0.2...0.6
- define returnlevel <math:(%difficulty%/<fl@pmsMaxDifficulty>)*%rangeDelta%+<def[valuelist].get[1]>>
}
else {
# Couldn't find range from provided list, trying to return first item in list. Will be null if list is empty.
- define returnLevel <def[valuelist].get[1]>
}
- determine <def[returnlevel]>
lerpIndex:
type: procedure
definitions: globalflagname|difficulty
script:
- if !<def[difficulty].exists> {
- narrate "Difficulty not specified, assuming 50%"
- define difficulty <fl@pmsMaxDifficulty.div[2]>
}
# map difficulty to number of items in list. Must be integer to access list via .get[i] later, thus .round at the end
- define itemlevel <def[difficulty].div[<fl@pmsMaxDifficulty>].mul[<fl@%globalflagname%.as_list.size>].round>
- determine <def[itemlevel]>
# each player adds pmsDifficultyIncreasePerPlayer (percent) difficulty
playerCountDifficulty:
type: procedure
definitions: difficulty
script:
- define playerCount <player.location.find.players.within[36].size>
# (( 15 * 3 - 15 )/100) * <fl@pmsMaxDifficulty>
- if <def[playerCount].is[MORE].than[1]> {
- define temp <math:((<fl@pmsDifficultyIncreasePerPlayer>*%playerCount%-<fl@pmsDifficultyIncreasePerPlayer>)/100+1)*<def[difficulty]>>
- determine <def[temp].round>
}
else {
- determine <def[difficulty]>
}
########################################################################################################################################
# spawnSummonWrapper
########################################################################################################################################
spawnSummonWrapper:
type: task
definitions: as_executor|location|entity|equip|difficulty|isBoss
script:
- define entityAttributes <def[entity].split[regex:\w@\w+\[]>
- define entityAttributes <def[entityAttributes].substring[0,<def[entityAttributes].length.sub_int[1]>].split[;]>
- foreach <def[entityAttributes]> {
- if <def[value].contains[<el@val[=]>]> {
- if <def[value].contains[custom_name]> {
- define custom_name <def[value].split[<el@val[=]>].get[2]>
}
else if <def[value].contains[max_health]> {
- define max_health <def[value].split[<el@val[=]>].get[2]>
}
else if <def[value].contains[health]> {
- define health <def[value].split[<el@val[=]>].get[2]>
}
else if <def[value].contains[movementSpeed]> {
- define movementSpeed <def[value].split[<el@val[=]>].get[2]>
}
else if <def[value].contains[attackDamage]> {
- define attackDamage <def[value].split[<el@val[=]>].get[2]>
}
else if <def[value].contains[followRange]> {
- define followRange <def[value].split[<el@val[=]>].get[2]>
}
else if <def[value].contains[knockbackResistance]> {
- define knockbackResistance <def[value].split[<el@val[=]>].get[2]>
}
else if <def[value].contains[skeleton]> && <def[value].split[<el@val[=]>].get[2].is[==].to[WITHER]> {
- define mobType "SkeletonType:1"
}
else if <def[value].contains[powered]> && <def[value].split[<el@val[=]>].get[2].is[==].to[true]> {
# TODO: radius and fuse should be variables
- define poweredCreeper "ExplosionRadius:3,Fuse:30,powered:1"
}
else if <def[value].contains[villager]> && <def[value].split[<el@val[=]>].get[2].is[==].to[true]> {
- define isVillager "IsVillager:1"
}
else if <def[value].contains[age]> && <def[value].split[<el@val[=]>].get[2].is[==].to[baby]> {
- define age "IsBaby:1"
}
else if <def[value].contains[skull]> {
# TODO if player skull is taken, name "Xericore the Shadow" or something
- define skull "id:skull,Damage:3,tag:{SkullOwner:<def[value].split[<el@val[=]>].get[2]>}"
}
else if <def[value].contains[jockey]> && <def[value].split[<el@val[=]>].get[2].is[==].to[true]> {
- define jockey "Riding:{id:Chicken,IsChickenJockey:1}"
}
#else if <def[value].contains[ActiveEffects]> {
# - define ActiveEffects <def[value].split[<el@val[=]>].get[2]>
#}
}
}
# need this to correctly support conversion of pig_zombie to PigZombie
- define summonEntity <def[entity].entity_type.to_titlecase>
# Only (Pig)Zombies and Skeletons will have equipment
- if <def[entity].entity_type.is[==].to[SKELETON]> || <def[entity].entity_type.is[==].to[ZOMBIE]> || <def[entity].entity_type.is[==].to[PIG_ZOMBIE]> {
- if <def[entity].entity_type.is[==].to[PIG_ZOMBIE]> {
- define anger "Anger:32767"
- define summonEntity PigZombie
}
- define equipChance <proc[lerp].context[pmsEquipRange|<def[difficulty]>|<def[isBoss]>]>
- define equipAttributs <def[equip].split[/]>
- foreach <def[equipAttributs]> {
- if <util.random.decimal.is[OR_LESS].than[<def[equipChance]>]> || <def[entity].entity_type.is[==].to[SKELETON]> {
# Skeletons always get weapons, otherwise they don't do anything.
- define equip true
}
else {
- define equip false
}
- if <def[value].contains[hand]> {
# bosses always have weapons
- if <def[isBoss]> || <def[equip]> {
- define hand <proc[getItemWithDurability].context[<def[value]>|<def[difficulty]>|<def[isBoss]>]>
}
}
else if <def[value].contains[head]> {
# Equip helmet always to prevent mobs from burning at day (you could use fire resistance as well, but I like this better)
- define head <proc[getItemWithDurability].context[<def[value]>|<def[difficulty]>|<def[isBoss]>]>
}
else if <def[value].contains[chest]> && <def[equip]> {
- define chest <proc[getItemWithDurability].context[<def[value]>|<def[difficulty]>|<def[isBoss]>]>
}
else if <def[value].contains[legs]> && <def[equip]> {
- define leggings <proc[getItemWithDurability].context[<def[value]>|<def[difficulty]>|<def[isBoss]>]>
}
else if <def[value].contains[boots]> && <def[equip]> {
- define boots <proc[getItemWithDurability].context[<def[value]>|<def[difficulty]>|<def[isBoss]>]>
}
else if <def[value].contains[DropChances]> {
- define DropChances <def[value]>
}
}
}
- execute <def[as_executor]> "summon <def[summonEntity]> <def[location].x> <def[location].y> <def[location].z>
{Equipment:[
{<tern[<def[hand].exists>]:<def[hand]>||>},
{<tern[<def[boots].exists>]:<def[boots]>||>},
{<tern[<def[leggings].exists>]:<def[leggings]>||>},
{<tern[<def[chest].exists>]:<def[chest]>||>},
{<tern[<def[skull].exists>]:<def[skull]>||<tern[<def[head].exists>]:<def[head]>||>>}]<tern[<def[custom_name].exists>]:,CustomName:<def[custom_name]>||>, Attributes : [ <tern[<def[max_health].exists>]:{Name : generic.maxHealth,Base : <def[max_health]>}||>
<tern[<def[movementSpeed].exists>]:,
{Name : generic.movementSpeed,Base : <def[movementSpeed]>}||> <tern[<def[attackDamage].exists>]:,
{Name : generic.attackDamage,Base : <def[attackDamage]>}||> <tern[<def[followRange].exists>]:,
{Name : generic.followRange,Base : <def[followRange]>}||> <tern[<def[knockbackResistance].exists>]:,
{Name : generic.knockbackResistance,Base : <def[knockbackResistance]>}||>]
<tern[<def[DropChances].exists>]:,<def[DropChances]>||><tern[<def[mobType].exists>]:,<def[mobType]>||>
<tern[<def[anger].exists>]:,<def[anger]>||>
<tern[<def[poweredCreeper].exists>]:,<def[poweredCreeper]>||>
#,ActiveEffects:[{Id:12,Amplifier:1,Duration:999999}]
<tern[<def[age].exists>]:,<def[age]>||>
<tern[<def[isVillager].exists>]:,<def[isVillager]>||>
<tern[<def[jockey].exists>]:,<def[jockey]>||>}"
#<tern[<def[ActiveEffects].exists>]:,<proc[getActiveEffectsFormatted].context[<def[ActiveEffects]>]>||>
getItemWithDurability:
type: procedure
definitions: item|difficulty|isBoss
script:
- define itemName <def[item].split[:].get[2]>
- define maxDurability <i@%itemName%.max_durability>
- define durabilityDifficulty <proc[lerp].context[pmsItemDamaged|<def[difficulty]>|<def[isBoss]>]>
- define randDurability <proc[gaussRand].context[<math:%durabilityDifficulty%*%maxDurability%>|0|%maxDurability%].round>
- determine <i@%itemName%[durability=%randDurability%].json>
getActiveEffectsFormatted:
type: procedure
definitions: ActiveEffects
script:
- define tempActiveEffects ,ActiveEffects:[
- foreach <def[ActiveEffects]> {
- define <def[tempActiveEffects]> %tempActiveEffects%
}
- determine 2
#{Id:22,Amplifier:1,Duration:999999},{Id:7,Amplifier:1,Duration:999999},{Id:16,Amplifier:1,Duration:999999}]