195 lines
7.5 KiB
Python
195 lines
7.5 KiB
Python
from direct.directnotify import DirectNotifyGlobal
|
|
from direct.distributed import DistributedObjectAI
|
|
|
|
from otp.avatar.DistributedPlayerAI import DistributedPlayerAI
|
|
from otp.otpbase import OTPGlobals
|
|
|
|
from toontown.spellbook.MagicWordConfig import *
|
|
from toontown.spellbook.MagicWordIndex import *
|
|
|
|
import json
|
|
import os
|
|
|
|
|
|
MagicWordIndex = magicWordIndex.copy()
|
|
|
|
spellbookJsonDefaultValues = '''{
|
|
"words":
|
|
[
|
|
{
|
|
"name": "SetPos",
|
|
"access": "USER"
|
|
},
|
|
{
|
|
"name": "GetPos",
|
|
"access": "USER"
|
|
}
|
|
]
|
|
}
|
|
'''
|
|
|
|
if not os.path.exists('config/'):
|
|
os.mkdir('config/')
|
|
|
|
if not os.path.isfile('config/spellbook.json'):
|
|
with open('config/spellbook.json', 'w') as data:
|
|
data.write(spellbookJsonDefaultValues)
|
|
data.close()
|
|
|
|
with open('config/spellbook.json') as data:
|
|
spellbook = json.load(data)
|
|
|
|
for word in spellbook['words']:
|
|
name = word['name']
|
|
accessLevel = word['access']
|
|
|
|
if accessLevel not in OTPGlobals.AccessLevelName2Int.keys():
|
|
break
|
|
|
|
try:
|
|
wordInfo = MagicWordIndex[str(name.lower())]
|
|
for alias in wordInfo['aliases']:
|
|
MagicWordIndex[alias]['access'] = accessLevel
|
|
except:
|
|
pass
|
|
|
|
|
|
class TTOffMagicWordManagerAI(DistributedObjectAI.DistributedObjectAI):
|
|
notify = DirectNotifyGlobal.directNotify.newCategory('TTOffMagicWordManagerAI')
|
|
|
|
def requestExecuteMagicWord(self, affectRange, affectType, affectExtra, lastClickedAvId, magicWord):
|
|
avId = self.air.getAvatarIdFromSender()
|
|
toon = self.air.doId2do.get(avId)
|
|
if not toon:
|
|
self.notify.warning('requestExecuteMagicWord: Magic Word use requested but invoker avatar is non-existant!')
|
|
return
|
|
|
|
targetIds = []
|
|
if affectRange in [AFFECT_SINGLE, AFFECT_BOTH]:
|
|
targetIds.append(avId)
|
|
|
|
if (affectRange in [AFFECT_OTHER, AFFECT_BOTH]) and affectType == AFFECT_SINGULAR:
|
|
if lastClickedAvId:
|
|
targetIds.append(lastClickedAvId)
|
|
else:
|
|
self.generateResponse(avId=avId, responseType = "NoTarget")
|
|
return
|
|
|
|
if affectType in [AFFECT_ZONE, AFFECT_SERVER, AFFECT_RANK]:
|
|
toonIds = []
|
|
for doId in self.air.doId2do.keys()[:]:
|
|
do = self.air.doId2do.get(doId)
|
|
if isinstance(do, DistributedPlayerAI) and do.isPlayerControlled() and do != toon:
|
|
if affectType == AFFECT_ZONE and do.zoneId == toon.zoneId:
|
|
toonIds.append(doId)
|
|
elif affectType == AFFECT_SERVER:
|
|
toonIds.append(doId)
|
|
elif affectType == AFFECT_RANK and do.getAccessLevel() == affectExtra:
|
|
toonIds.append(doId)
|
|
|
|
if not toonIds and not targetIds:
|
|
self.generateResponse(avId=avId, responseType = "NoTarget")
|
|
return
|
|
|
|
targetIds += toonIds
|
|
|
|
if not targetIds:
|
|
self.generateResponse(avId=avId, responseType = "NoTarget")
|
|
return
|
|
|
|
for targetId in targetIds:
|
|
if targetId == avId:
|
|
continue
|
|
targetToon = self.air.doId2do.get(targetId)
|
|
if not targetToon:
|
|
continue
|
|
if targetToon.getAccessLevel() >= toon.getAccessLevel():
|
|
targetIds.remove(targetId)
|
|
continue
|
|
|
|
if len(targetIds) == 0:
|
|
self.generateResponse(avId=avId, responseType = "NoAccessToTarget")
|
|
|
|
magicWord, args = (magicWord.split(' ', 1) + [''])[:2]
|
|
magicWord = magicWord.lower()
|
|
magicWordInfo = MagicWordIndex[magicWord]
|
|
|
|
if affectRange not in magicWordInfo['affectRange']:
|
|
self.generateResponse(avId=avId, responseType = "RestrictionOther")
|
|
return
|
|
|
|
if toon.getAccessLevel() < OTPGlobals.AccessLevelName2Int.get(magicWordInfo['access']):
|
|
self.generateResponse(avId=avId, responseType = "NoAccess")
|
|
return
|
|
|
|
if self.air.defaultAccessLevel == 'NO_ACCESS':
|
|
if not magicWordInfo['administrative']:
|
|
self.generateResponse(avId=avId, responseType = "LegitServer")
|
|
return
|
|
|
|
commandArgs = magicWordInfo['args']
|
|
maxArgs = len(commandArgs)
|
|
minArgs = 0
|
|
argList = args.split(None, maxArgs-1)
|
|
for argSet in commandArgs:
|
|
isRequired = argSet[ARGUMENT_REQUIRED]
|
|
if isRequired:
|
|
minArgs += 1
|
|
|
|
if len(argList) < minArgs:
|
|
self.generateResponse(avId=avId, responseType = "NotEnoughArgs", extraMessageData = "{} argument{}".format(minArgs, "s" if minArgs != 1 else ''))
|
|
return
|
|
elif len(argList) > maxArgs:
|
|
self.generateResponse(avId=avId, responseType = "TooManyArgs", extraMessageData = "{} argument{}".format(maxArgs, "s" if maxArgs != 1 else ''))
|
|
return
|
|
|
|
parsedArgList = []
|
|
|
|
if len(argList) < maxArgs:
|
|
for x in range(minArgs,maxArgs):
|
|
if commandArgs[x][ARGUMENT_REQUIRED] or len(argList) >= x+1:
|
|
continue
|
|
argList.append(commandArgs[x][ARGUMENT_DEFAULT])
|
|
|
|
for x in xrange(len(argList)):
|
|
arg = argList[x]
|
|
argType = commandArgs[x][ARGUMENT_TYPE]
|
|
try:
|
|
parsedArg = argType(arg)
|
|
except:
|
|
self.generateResponse(avId=avId, responseType = "BadArgs")
|
|
return
|
|
|
|
parsedArgList.append(parsedArg)
|
|
|
|
if magicWordInfo['execLocation'] == EXEC_LOC_CLIENT:
|
|
self.sendClientCommand(avId, magicWord, magicWordInfo['classname'], targetIds=targetIds, parsedArgList=parsedArgList, affectRange=affectRange,
|
|
affectType=affectType, affectExtra=affectExtra, lastClickedAvId=lastClickedAvId)
|
|
else:
|
|
command = getMagicWord(magicWordInfo['classname'])
|
|
command = command(self.air, None, avId, targetIds, parsedArgList)
|
|
returnValue = command.executeWord()
|
|
if returnValue:
|
|
self.generateResponse(avId=avId, responseType = "Success", returnValue=returnValue)
|
|
else:
|
|
self.generateResponse(avId=avId, responseType = "SuccessNoResp", magicWord=magicWord, parsedArgList=parsedArgList,
|
|
affectRange=affectRange, affectType=affectType, affectExtra=affectExtra,
|
|
lastClickedAvId=lastClickedAvId)
|
|
|
|
def generateResponse(self, avId, responseType = "BadWord", magicWord='', parsedArgList=None, returnValue='', affectRange=0,
|
|
affectType=0, affectExtra=0, lastClickedAvId=0, extraMessageData=''):
|
|
if not parsedArgList:
|
|
parsedArgList = []
|
|
|
|
parsedArgList = json.dumps(parsedArgList)
|
|
self.sendUpdateToAvatarId(avId, 'generateResponse',
|
|
[responseType, magicWord, parsedArgList, returnValue, affectRange, affectType,
|
|
affectExtra, lastClickedAvId, extraMessageData])
|
|
|
|
def sendClientCommand(self, avId, word, commandName, targetIds=[], parsedArgList=None, affectRange=0,
|
|
affectType=0, affectExtra=0, lastClickedAvId=0):
|
|
if not parsedArgList:
|
|
parsedArgList = []
|
|
|
|
parsedArgList = json.dumps(parsedArgList)
|
|
self.sendUpdateToAvatarId(avId, "executeMagicWord", [word, commandName, targetIds, parsedArgList, affectRange, affectType, affectExtra, lastClickedAvId])
|