Add script for amulet of finding

These pieces of jewelry help players remember locations on the world
map. Players can bind an amulet at any location on the world map.
Applying a bound amulet shows players a message indicating which
direction they should travel to return to the bound location.

Since this shares some code with the Rhyzian amulet, move the shared
code to CFWorld. While here, improve the getdir() function to round the
direction to the closest compass direction.
master
Kevin Zheng 2022-03-27 21:35:58 -07:00
parent fa55a0c63a
commit 82079a2faa
3 changed files with 103 additions and 26 deletions

View File

@ -1,5 +1,7 @@
#CFWorld.py
#A small module for checking where is bigworld an object is if it's in bigworld.
import math
import Crossfire
world_prefix = "/world/world_"
@ -18,3 +20,18 @@ def loc_from_ob(ob):
x = (int(strloc[0]) * bigmapxsize) + ob.X
y = (int(strloc[1]) * bigmapysize) + ob.Y
return (x, y)
def getdiff(loc1, loc2):
return (loc1[0]-loc2[0], loc1[1]-loc2[1])
def getdir(v):
x, y = v
t = math.atan2(x, y)
rt = round(t / (math.pi/4)) # between -4 and 4
directions = ["north", "northwest", "west", "southwest", "south", "southeast", "east", "northeast"]
dir_str = directions[(rt + 4)%8]
return dir_str
#outputs in furlongs (outdoor tiles)
def getdist(loc):
return int(math.sqrt((loc[0]*loc[0])+(loc[1]*loc[1])))

View File

@ -0,0 +1,83 @@
# finding.py -- apply event for amulets of finding
#
# These pieces of jewelry help players remember locations on the world map.
# Players can bind an amulet at any location on the world map. Applying a bound
# amulet shows players a message indicating which direction they should travel
# to return to the bound location.
#
# The bound location is stored in the key-value pair "finding_location", which
# contains a 2-tuple of global coordinates from the CFWorld module.
import Crossfire
import CFWorld
location_key = 'finding_location'
world_size = 50
def indefinite(ob):
"""Append 'a' or 'an' to the given object's name."""
name = ob.QueryName()
if name[0].lower() in {'a', 'e', 'i', 'o'}:
article = "an"
else:
article = "a"
return article + " " + name
def auto_identify(ob, pl):
"""Identify the object if it hasn't already."""
if not ob.Identified:
ob.Identified = True
pl.Message("This is %s!" % indefinite(ob))
def loc_to_str(l):
return ",".join(map(str, l))
def str_to_loc(s):
return list(map(int, s.split(",")))
def describe_vec(v):
dist = CFWorld.getdist(v)
if dist < 1:
return "here"
if dist <= world_size:
modifier = "strongly"
elif dist <= 5*world_size:
modifier = "moderately"
else:
modifier = "lightly"
return modifier + " " + CFWorld.getdir(v)
def on_apply():
whoami = Crossfire.WhoAmI()
player = Crossfire.WhoIsActivator()
Crossfire.SetReturnValue(1) # do not allow players to wear this
auto_identify(whoami, player)
if whoami.Env == player:
# applied in inventory
current_location = CFWorld.loc_from_ob(player)
else:
# applied on the floor
current_location = CFWorld.loc_from_ob(whoami)
if current_location == False:
# can only be used on the world map
player.Message("The %s rattles for a moment, then stops." % whoami.QueryName())
return
if whoami.Env == player:
# applied in inventory
stored_str = whoami.ReadKey(location_key)
if stored_str == "":
# no location bound
player.Message("The %s vibrates for a moment, then stops." % whoami.QueryName())
return
stored_location = str_to_loc(stored_str)
delta = CFWorld.getdiff(stored_location, current_location)
player.Message("The %s tugs you %s." % (whoami.QueryName(), describe_vec(delta)))
else:
# applied on the floor
whoami.WriteKey(location_key, loc_to_str(current_location), 1)
player.Message("The %s glows blue." % whoami.QueryName())
on_apply()

View File

@ -1,43 +1,20 @@
import Crossfire
import CFWorld
import math
scorn_loc = (5272, 5786)
navar_loc = (6112, 5850)
Crossfire.SetReturnValue( 1 )
def getdiff(loc1, loc2):
return (loc1[0]-loc2[0], loc1[1]-loc2[1])
def getdir(loc1, loc2):
loc = getdiff(loc1, loc2)
if (loc[1] > 0):
start="south"
elif(loc[1] < 0):
start="north"
else:
start=""
if (loc[0] > 0):
return start+"east"
elif(loc[0] < 0):
return start+"west"
else:
return start
#outputs in furlongs (outdoor tiles)
def getdist(loc1, loc2):
loc = getdiff(loc1, loc2)
return int(math.sqrt((loc[0]*loc[0])+(loc[1]*loc[1])))
#outputs in miles
def getuserdist(dist):
return (int(dist/8.0+0.5))
def gettext(loc1, loc2, name):
loc_raw_dist = getdist(loc1, loc2)
diff = CFWorld.getdiff(loc2, loc1)
loc_raw_dist = CFWorld.getdist(diff)
loc_dist = getuserdist(loc_raw_dist)
loc_dir = getdir(loc2, loc1)
loc_dir = CFWorld.getdir(diff)
if (abs(loc_dist) > 5):
loc_distmsg = "A "+name+" arrow flashes "+str(loc_dist)+" times"
else: