Exemple #1
0
def OnControlKey(ki, controlKey, activeFlag):
    if not xxConfig.hasAdminLevel(): return
    global isForward
    global isBackward
    global isLeft
    global isRight
    global isUp
    global isDown
    global isRun
    global isAccel
    global isRotLeft
    global isRotRight
    global spaceBarDown
    # keep these status keysalways up-to-date
    if (controlKey == PlasmaControlKeys.kKeyModFast):
        isRun = activeFlag
    elif (controlKey == PlasmaControlKeys.kKeyAlwaysRun):
        isAccel = activeFlag
    # enable/disable flymode via "Esc" key
    elif (controlKey == PlasmaControlKeys.kKeyExitMode):
        if activeFlag:
            if len(flyingObjects): DisableFlymode()
            else: EnableFlymode([PtGetLocalAvatar()], ki)
    # movement keys
    elif (controlKey == PlasmaControlKeys.kKeyMoveForward):
        isForward = activeFlag
    elif (controlKey == PlasmaControlKeys.kKeyMoveBackward):
        isBackward = activeFlag
    elif (controlKey == PlasmaControlKeys.kKeyStrafeLeft):
        isLeft = activeFlag
    elif (controlKey == PlasmaControlKeys.kKeyStrafeRight):
        isRight = activeFlag
    elif (controlKey == PlasmaControlKeys.kKeyRotateLeft):
        isRotLeft = activeFlag
    elif (controlKey == PlasmaControlKeys.kKeyRotateRight):
        isRotRight = activeFlag
    elif (controlKey == PlasmaControlKeys.kKeyCamZoomIn):
        isDown = activeFlag
    elif (controlKey == PlasmaControlKeys.kKeyCamZoomOut):
        isUp = activeFlag
    elif (controlKey == PlasmaControlKeys.kKeyJump):
        if spaceBarDown: isDown = activeFlag
        else: isUp = activeFlag
        if not activeFlag: spaceBarDown = not spaceBarDown # toggle down/up move on key up
    # online we update the position others see on key down & up only
    if xxConfig.isOnline():
        for object in flyingObjects: # this will only do something if there are objects in this array
            object.netForce(1)
            object.physics.warp(object.getLocalToWorld())
Exemple #2
0
def OnTimer(ki, id):
    if not xxConfig.hasAdminLevel(): return False
    # due to this check, you can only use FLymode if you have the admin rights on startup already - on the other hand, it saves all the others from needlessly running this timer
    if id == xUserKI.kFlyModeTimer:
        if not len(flyingObjects):
            global flyTimerRunning
            flyTimerRunning = False
            return
        doStep()
        PtAtTimeCallback(ki.key, callbackRate, xUserKI.kFlyModeTimer)
        return True
    elif id == xUserKI.kReposTimer:
        for object in flyingObjects:
            object.netForce(1)
            object.physics.disable()
            object.physics.warp(object.getLocalToWorld())
            if flyIsHidden: object.draw.disable()
        return True
    return False
Exemple #3
0
def OnDefaultKey(ki, isShift, isCtrl, keycode):
    if not xxConfig.hasAdminLevel(): return
    if (not isCtrl) and (not isShift):
        global currentLinearSpeed
        global currentRotationSpeed
        global callbackRate
        global currentStrafeMotion
        global lastJumpUp
        if (keycode == 120): # F9
            if (currentStrafeMotion == 'd'):
                currentStrafeMotion = 'x'
            elif (currentStrafeMotion == 'x'):
                currentStrafeMotion = 'y'
            else:
                currentStrafeMotion = 'd'
            return
        elif (keycode == 121): # F10
            for object in flyingObjects:
                newMat = ptMatrix44()
                pos = object.position()
                newMat.translate(ptVector3(pos.getX(), pos.getY(), pos.getZ()))
                object.netForce(1)
                object.physics.warp(newMat)
            return
        elif (keycode == 122): # F11
            currentLinearSpeed = defaultLinearSpeed
            currentRotationSpeed = defaultRotationSpeed
            callbackRate = defaultCallbackRate
            return
        elif (keycode == 123): # F12
            callbackRate = (0.9 * callbackRate)
            if (callbackRate < 0.005):
                callbackRate = 0.005
            return
        elif (keycode == 45): # Insert
            currentLinearSpeed = (0.8 * currentLinearSpeed)
            return
        elif (keycode == 145): # Scroll lock
            currentRotationSpeed = (0.8 * currentRotationSpeed)
            return
Exemple #4
0
def OnCommand(ki, arg, cmnd, args, playerList, KIContent, silent):
    if not xxConfig.hasAdminLevel(): return
    global loopInterval, loopCount, loopCmd, loopTimerActive  # loop variables
    global tourName, tourInterval, tourStep, tourCam, tourTimerActive  # tour variables
    # developer commands
    if (cmnd == 'console' or (xxConfig.isOnline() and cmnd == 'consolenet')):
        (valid, null) = xUserKI.GetArg(ki, cmnd, args, 'UruConsole command',
                                       lambda args: len(args) > 0)
        if not valid: return True
        if cmnd == 'consolenet':
            PtConsoleNet(arg, 1)
            if not silent: ki.IAddRTChat(None, 'UruConsoleNet: %s' % arg, 0)
        else:
            PtConsole(arg)
            if not silent: ki.IAddRTChat(None, 'UruConsole: %s' % arg, 0)
        return True
    if (cmnd == 'loadpage'):
        (valid, null) = xUserKI.GetArg(ki, cmnd, args, 'page name',
                                       lambda args: len(args) > 0)
        if not valid: return True
        PtPageInNode(arg)
        if not silent: ki.IAddRTChat(None, 'Loaded page %s' % arg, 0)
        return True
    if (cmnd == 'exec'):
        (valid, null) = xUserKI.GetArg(ki, cmnd, args, 'Python command',
                                       lambda args: len(args) > 0)
        if not valid: return True
        ExecPython(arg)
        return True
    if (cmnd == 'getchron'):
        (valid, name) = xUserKI.GetArg(ki, cmnd, args, 'chronicle name',
                                       lambda args: len(args) == 1,
                                       lambda args: args[0])
        if not valid: return True
        value = xUserKI.GetChronicle(name)
        if (value != None):
            if not silent: ki.IAddRTChat(None, '%s = %s' % (name, value), 0)
        else:
            ki.IDoErrorChatMessage("Chronicle '%s' doesn't exist." % name)
        return True
    if (cmnd == 'getversion'):
        (valid, player) = xUserKI.GetArg(
            ki, cmnd, args, 'player', lambda args: len(args) == 1,
            lambda args: xUserKI.GetPlayer(ki, args[0], playerList))
        if not valid or not player: return True
        if isinstance(player, ptPlayer):
            if not silent:
                ki.IAddRTChat(
                    None,
                    'Requesting KI version from %s' % player.getPlayerName(),
                    0)
            xUserKI.SendRemoteCall(ki, 'getversion', [player])
        return True
    if (cmnd == 'about'):
        (valid, object) = xUserKI.GetArg(
            ki, cmnd, args, 'object to analyze', lambda args: len(args) == 1,
            lambda args: xUserKI.GetObject(
                ki, args[0], playerList, mustHaveCoord=False))
        if not valid or not object: return True
        if object.isAvatar():
            curBrainMode = object.avatar.getCurrentMode()
            if (curBrainMode == PtBrainModes.kAFK):
                avmode = 'afk'
            elif (curBrainMode == PtBrainModes.kSit):
                avmode = 'sitting'
            elif (curBrainMode == PtBrainModes.kLadder):
                avmode = 'climbing a ladder'
            elif (curBrainMode == PtBrainModes.kNonGeneric):
                avmode = 'idle'
            else:
                avmode = 'in unknown state %d' % curBrainMode
            if not silent:
                ki.IAddRTChat(
                    None, '%s is an avatar and currently %s' %
                    (xUserKI.GetObjectName(object), avmode), 0)
        else:
            if object.isLocallyOwned():
                ownstr = 'locally owned'
            else:
                ownstr = 'not locally owned'
            if not silent:
                ki.IAddRTChat(
                    None, '%s is an object and %s' %
                    (xUserKI.GetObjectName(object), ownstr), 0)
        return True
    if (cmnd == 'autolink'):
        (valid, age) = xUserKI.GetArg(ki, cmnd, args, 'age filename|disable',
                                      lambda args: len(args) == 1,
                                      lambda args: args[0])
        if not valid: return True
        if age.lower() == 'disable':
            xUserKI.SetChronicle(kAutoLinkChronicle, '')
            ki.IAddRTChat(None, 'Disabled auto-linking on startup', 0)
        else:
            # verify auto-link age
            als = xUserKI.GetAgeLinkStruct(ki, age)
            if not als: return True
            xUserKI.SetChronicle(kAutoLinkChronicle, age)
            ki.IAddRTChat(
                None, 'On next startup, you will be auto-linked to %s' %
                als.getAgeInfo().getAgeInstanceName(), 0)
        return True
# linking commands
    if (cmnd in ['link', 'linksp']):
        if cmnd == 'link':
            (valid, data) = xUserKI.GetArg(
                ki, cmnd, args, 'age filename> <[list of players]',
                lambda args: len(args) >= 1, lambda args: ((args[
                    0], None), xUserKI.GetPlayers(ki, args[1:], playerList)))
        else:
            (valid, data) = xUserKI.GetArg(
                ki, cmnd, args,
                'age filename> <spawn point name> <[list of players]',
                lambda args: len(args) >= 2, lambda args: ((args[0], args[
                    1]), xUserKI.GetPlayers(ki, args[2:], playerList)))
        if not valid or not data[1]: return True
        # find out where to link
        onlyMe = len(
            data[1]) == 1 and data[1][0].getPlayerID() == PtGetLocalClientID()
        als = xUserKI.GetAgeLinkStruct(
            ki, data[0][0], data[0][1], needFullInfo=not onlyMe
        )  # if a player was manually specified, we need the full UUID
        if type(als) == type(None): return True
        # link the players
        linkMgr = ptNetLinkingMgr()
        linkMgr.setEnabled(1)
        for player in data[1]:
            if not silent:
                ki.IAddRTChat(
                    None, 'Linking %s to %s' %
                    (player.getPlayerName(),
                     als.getAgeInfo().getAgeInstanceName()), 0)
            if onlyMe:
                linkMgr.linkToAge(
                    als
                )  # we have an incomplete linking struct, so we need to use this linking function
            else:
                linkMgr.linkPlayerToAge(als, player.getPlayerID())
        return True
    if (cmnd == 'linkto'):
        (valid, player) = xUserKI.GetArg(
            ki, cmnd, args, 'player', lambda args: len(args) == 1,
            lambda args: xUserKI.GetPlayer(ki, args[0], playerList))
        if not valid or not player: return True
        # link the player
        linkMgr = ptNetLinkingMgr()
        linkMgr.setEnabled(1)
        linkMgr.linkToPlayersAge(player.getPlayerID())
        if not silent:
            ki.IAddRTChat(None, 'Linking you to %s' % player.getPlayerName(),
                          0)
        return True
    if (cmnd == 'linkhere'):
        (valid, players) = xUserKI.GetArg(
            ki, cmnd, args, 'list of players', lambda args: len(args) >= 1,
            lambda args: xUserKI.GetPlayers(ki, args, playerList))
        if not valid or not players: return True
        # link the players
        linkMgr = ptNetLinkingMgr()
        linkMgr.setEnabled(1)
        for player in players:
            linkMgr.linkPlayerHere(
                player.getPlayerID())  # thanks to DarkFalkon for this line
            if not silent:
                ki.IAddRTChat(None,
                              'Linking %s to you' % player.getPlayerName(), 0)
        return True
# loop commands
    if (cmnd == 'loopstart'):
        loopCmd = ''
        (valid, data) = xUserKI.GetArg(
            ki, cmnd, args, 'interval> <command>|<interval> <count> <command',
            lambda args: xUserKI.IsFloat(args[0]) and
            (args[1].startswith('/') or
             (xUserKI.IsInt(args[1]) and args[2].startswith('/'))))
        if not valid: return True
        # get data
        loopInterval = float(args[0])
        loopCount = -1
        loopCmd = string.join(args[1:], " ")
        if not args[1].startswith(
                '/'):  # due to the GetArg args[1] must be an int in this case
            loopCount = int(args[1])
            loopCmd = string.join(args[2:], " ")
        # start timer
        OnTimer(ki, xUserKI.kLoopTimer)
        return True
    if (cmnd == 'loopstop'):
        loopCmd = ''
        return True
    if (cmnd == 'm'):
        (valid, data) = xUserKI.GetArg(
            ki, cmnd, args, 'command 1> & <command 2> & ... & <command n',
            lambda args: args[0].startswith('/') and string.join(args).find(
                '&') >= 0)
        if not valid: return True
        commands = arg.split('&')
        for command in commands:
            if (ki.ICheckChatCommands(command.strip(), silent) != None):
                ki.IDoErrorChatMessage(
                    "'%s' does not seem to be a KI command" % command.strip())
        return True
# General age and SDL control
    if (cmnd == 'set'):
        (valid, data) = xUserKI.GetArg(
            ki, cmnd, args, 'option to be set> <value',
            lambda args: len(args) == 2, lambda args: (args[0], int(args[1])),
            lambda args: len(args) == 1 and args[0] in ['list', 'listall'],
            lambda args: (args[0], -1))
        if not valid: return True
        (option, value) = data
        # get the option data
        if option == 'listall':
            ki.IAddRTChat(
                None, 'The following options are available: %s' %
                xUserKI.JoinListRec(setData), 0)
            return True
        age = PtGetAgeName()
        if not age in setData:
            ki.IDoErrorChatMessage(
                'There\'s nothing to be set in this age. Options are available in: %s'
                % xUserKI.JoinList(setData))
            return True
        ageData = setData[age]
        if option == 'list':
            ki.IAddRTChat(
                None, 'The following options are available in this age: %s' %
                xUserKI.JoinList(ageData), 0)
            return True
        if not option in ageData:
            ki.IDoErrorChatMessage(
                'There is no option called \'%s\' in this age. Use one of the following: %s'
                % (option, xUserKI.JoinList(ageData)))
            return True
        # apply option
        if len(ageData[option]):
            # it's a stanard boolean option
            if value not in [0, 1]:
                ki.IDoErrorChatMessage(
                    'Invalid value, allowed values are 0 and 1')
                return True
            for sdl in ageData[option]:
                xUserKI.SetSDL(sdl, 0, value)
        else:
            # one of the special options
            if age == 'city' and option == 'stage':
                if value not in [0, 1, 2]:
                    ki.IDoErrorChatMessage(
                        'Invalid value %d - must be 0 to 2' % value)
                    return True
                xUserKI.SetSDL('islmDRCStageState', 0, value)
            elif age == 'Neighborhood' and option in [
                    'gzglass', 'delinglass', 'tsogalglass'
            ]:
                if value not in [1, 2, 3]:
                    ki.IDoErrorChatMessage(
                        'Invalid value %d - must be 1 to 3' % value)
                    return True
                values = [0, 0, 0]
                values[
                    value -
                    1] = 1  # everything is 0 except for the one we are speaking about
                # these are the prefices
                prefices = {
                    'gzglass': 'nb01GZStainGlass0',
                    'delinglass': 'nb01EderDelinStainedGlass0',
                    'tsogalglass': 'nb01EderTsogalGlass0'
                }
                # set values
                for i in range(1, 4):
                    SDLName = '%s%dVis' % (prefices[option], i)
                    xUserKI.SetSDL(SDLName, 0, values[i - 1])
            elif age == 'Neighborhood' and option == 'heek':
                if value not in [0, 1, 2, 3]:
                    ki.IDoErrorChatMessage(
                        'Invalid value %d - must be 0 to 3' % value)
                    return True
                xUserKI.SetSDL('nb01Ayhoheek5Man1State', 0, value)
            else:
                ki.IDoErrorChatMessage(
                    'Unexpected error - unknown special option %s' % option)
                return True
        if not silent: ki.IAddRTChat(None, 'Set %s to %d' % (option, value), 0)
        return True
    if (cmnd == 'listsdl'):
        (valid, grep) = xUserKI.GetArg(ki, cmnd, args, '[filter]',
                                       lambda args: len(args) == 0,
                                       lambda args: (''),
                                       lambda args: len(args) == 1,
                                       lambda args: (args[0].lower()))
        if not valid: return True
        sdl = ptAgeVault().getAgeSDL()
        vars = sdl.getVarList()
        if len(grep): vars = filter(lambda s: s.lower().find(grep) >= 0, vars)
        if len(vars) == 0:
            ki.IAddRTChat(None, 'No SDL Variable found', 0)
        else:
            ki.IAddRTChat(None, '%d SDL Variable(s) found:' % len(vars), 0)
            line = ''
            for var in vars:
                if len(line): line += ', '
                line += var
            ki.IAddRTChat(None, line, 0)
        return True
    if (cmnd == 'setsdl'):
        (valid, data) = xUserKI.GetArg(ki, cmnd, args,
                                       'SDL var name> <integer value',
                                       lambda args: len(args) == 2,
                                       lambda args: (args[0], int(args[1])))
        if not valid: return True
        try:
            oldval = xUserKI.GetSDL(data[0], 0)
            xUserKI.SetSDL(data[0], 0, data[1])
            if not silent:
                ki.IAddRTChat(
                    None, 'Set SDL var %s to %d (old value: %s)' %
                    (data[0], data[1], oldval), 0)
        except Exception, detail:
            ki.IDoErrorChatMessage('Unable to set SDL var %s: %s' %
                                   (data[0], detail))
        return True
Exemple #5
0
def OnTimer(ki, id):  # called by xUserKI
    if not xxConfig.hasAdminLevel(): return
    global loopInterval, loopCount, loopCmd, loopTimerActive  # loop variables
    global tourName, tourInterval, tourStep, tourCam, tourTimerActive  # tour variables
    if id == xUserKI.kLoopTimer:
        loopTimerActive = False
        if not len(loopCmd):
            ki.IAddRTChat(None, 'Loop stopped', 0)
            return
        if (ki.ICheckChatCommands(loopCmd.strip(), silent=True) != None):
            ki.IDoErrorChatMessage("'%s' does not seem to be a KI command" %
                                   loopCmd.strip())
        if loopCount > 0:
            loopCount = loopCount - 1
        if loopCount == 0:
            ki.IAddRTChat(None, 'Loop count reached, stopped it', 0)
            return
        PtAtTimeCallback(ki.key, loopInterval, xUserKI.kLoopTimer)
        loopTimerActive = True
        return True
    if id == xUserKI.kAutoLinkPrepareTimer:
        # this will only be called once age loading is finished, so start the actual timer now!
        PtAtTimeCallback(ki.key, 2.5, xUserKI.kAutoLinkTimer)
        return True
    if id == xUserKI.kAutoLinkTimer:
        autoLinkAge = xUserKI.GetChronicle(kAutoLinkChronicle, '')
        if not len(autoLinkAge): return True
        als = xUserKI.GetAgeLinkStruct(ki, autoLinkAge)
        if not als: return True
        # link us
        ki.IAddRTChat(
            None,
            'Linking you automatically to %s (type "/autolink disable" to disable this)'
            % als.getAgeInfo().getAgeInstanceName(), 0)
        linkMgr = ptNetLinkingMgr()
        linkMgr.linkToAge(als)
        return True
    if id == xUserKI.kTourTimer:
        tourTimerActive = False
        if not len(tourName): return
        # preparation
        age = PtGetAgeName()
        try:
            tourList = xUserKIData.CameraTours[age][tourName]
        except:
            tourName = ''  # tour not found, or data module missing
            ki.IDoErrorChatMessage('Specified tour not found')
            return
        # let's go
        if tourStep >= len(tourList):
            ki.IAddRTChat(None, 'Tour %s has completed!' % tourName, 0)
            tourName = ''
        else:
            try:
                SetCamera(tourCam, tourList[tourStep])
                tourStep = tourStep + 1
                PtAtTimeCallback(ki.key, tourInterval, xUserKI.kTourTimer)
                tourTimerActive = True
            except:
                ki.IDoErrorChatMessage('Could not continue tour')
                tourName = ''
        return True
    return False
Exemple #6
0
def OnCommand(ki, arg, cmnd, args, playerList, KIContent, silent):
    if not xxConfig.hasAdminLevel(): return
    global flyingObjects, flyIsHidden
    if (cmnd == 'flymode'):
        (valid, objects) = xUserKI.GetArg(ki, cmnd, args, '[list of objects]',
          lambda args: len(args) >= 1, lambda args: xUserKI.GetObjects(ki, args, playerList),
          lambda args: len(args) == 0, lambda args: xUserKI.GetObjects(ki, ['me'], playerList)) # default to local player ("me")
        if not valid or not objects: return True
        # release previously bound objects
        if len(flyingObjects): ki.IDoErrorChatMessage('You are already flying!')
        else:
            EnableFlymode(objects, ki)
            if not silent: ki.IAddRTChat(None, 'Enabled Flymode', 0)
        return True
    if (cmnd == 'noflymode'):
        if not len(flyingObjects): ki.IDoErrorChatMessage('You are not flying curretnly!')
        else:
            if flyIsHidden:
                ki.IAddRTChat(None, 'Disabled permanent hiding of objects without showing these objects to you - they are now just normally hidden', 0)
            DisableFlymode() # this is put in a helper function to be able to provide other ways of controling flymode
            if not silent: ki.IAddRTChat(None, 'Disabled Flymode', 0)
        return True
    # object manipulation commands needing arguments
    if (cmnd == 'xyz'):
        (valid, data) = xUserKI.GetArg(ki, cmnd, args, 'relative x coordinate> <relative y coordinate> <relative z coordinate> <[list of objects]',
          lambda args: len(args) >= 3, lambda args: (float(args[0]), float(args[1]), float(args[2]), xUserKI.GetObjects(ki, args[3:], playerList)))
        if not valid or not data[3]: return True
        # warp them
        for object in data[3]:
            xUserKI.WarpObjectRelative(object, data[0], data[1], data[2])
            if not silent: ki.IAddRTChat(None, 'Moved %s by (%1.2f|%1.2f|%1.2f)' % (xUserKI.GetObjectName(object), data[0], data[1], data[2]), 0)
        return True
    if (cmnd in ['x', 'y', 'z']):
        (valid, data) = xUserKI.GetArg(ki, cmnd, args, 'relative %s coordinate> <[list of objects]' % cmnd,
          lambda arg: len(args) >= 1, lambda arg: (float(args[0]), xUserKI.GetObjects(ki, args[1:], playerList)))
        if not valid or not data[1]: return True
        # warp them
        for object in data[1]:
            if (cmnd == 'x'):
                xUserKI. WarpObjectRelative(object, data[0], 0, 0)
            elif (cmnd == 'y'):
                xUserKI.WarpObjectRelative(object, 0, data[0], 0)
            elif (cmnd == 'z'):
                xUserKI.WarpObjectRelative(object, 0, 0, data[0])
            if not silent: ki.IAddRTChat(None, 'Moved %s by %1.2f along the %s-axis' % (xUserKI.GetObjectName(object), data[0], cmnd), 0)
        return True
# object manipulation commands which don't need further arguments
    if (cmnd in ['hide', 'show']):
        (valid, objects) = xUserKI.GetArg(ki, cmnd, args, '[list of objects]',
          lambda args: True, lambda args: xUserKI.GetObjects(ki, args, playerList, mustHaveCoord = False))
        if not valid or not objects: return True
        # hide/show them
        for object in objects:
            object.netForce(1)
            if (cmnd == 'hide'):
                object.draw.disable()
                if not silent: ki.IAddRTChat(None, 'Successfully hid %s' % xUserKI.GetObjectName(object), 0)
            elif (cmnd == 'show'):
                object.draw.enable()
                if not silent: ki.IAddRTChat(None, 'Successfully showed %s' % xUserKI.GetObjectName(object), 0)
        if (not len(args)) and len(flyingObjects):
            flyIsHidden = (cmnd == 'hide')
            if not silent:
                if flyIsHidden:
                    ki.IAddRTChat(None, 'These objects are now permanently hidden, even new players joining will not see them', 0)
                else:
                    ki.IAddRTChat(None, 'Permanent hiding is now disabled', 0)
        elif flyIsHidden and cmnd == 'show' and not silent:
            ki.IAddRTChat(None, 'You just showed an object while permanent hiding of controlled objects was enabled, so you might be faced to strange happenings', 0)
        return True
    if (cmnd in ['normalize', 'repos', 'location', 'ghost', 'unghost']):
        (valid, objects) = xUserKI.GetArg(ki, cmnd, args, '[list of objects]',
          lambda args: True, lambda args: xUserKI.GetObjects(ki, args, playerList))
        if not valid or not objects: return True
        # do with them what we want to do
        for object in objects:
            object.netForce(1)
            if (cmnd == 'normalize'):
                newMat = ptMatrix44()
                pos = object.position()
                newMat.translate(ptVector3(pos.getX(), pos.getY(), pos.getZ()))
                object.physics.warp(newMat)
                if not silent: ki.IAddRTChat(None, 'Successfully normalized %s' % xUserKI.GetObjectName(object), 0)
            elif (cmnd == 'repos'):
                object.physics.warp(object.getLocalToWorld())
                if not silent: ki.IAddRTChat(None, 'Successfully repositioned %s' % xUserKI.GetObjectName(object), 0)
            elif (cmnd == 'location' and not silent):
                pos = object.position()
                at = object.view()
                up = object.up()
                ki.IAddRTChat(None, ('%s is at the position (%1.2f|%1.2f|%1.2f)' % (xUserKI.GetObjectName(object), pos.getX(), pos.getY(), pos.getZ())), 0)
                ki.IAddRTChat(None, ('%s is looking at (%1.2f|%1.2f|%1.2f)' % (xUserKI.GetObjectName(object), at.getX(), at.getY(), at.getZ())), 0)
                ki.IAddRTChat(None, ('%s has (%1.2f|%1.2f|%1.2f) above its head' % (xUserKI.GetObjectName(object), up.getX(), up.getY(), up.getZ())), 0)
            elif (cmnd == 'ghost'):
                object.physics.suppress(True)
                if not silent: ki.IAddRTChat(None, 'Successfully ghostified %s' % xUserKI.GetObjectName(object), 0)
            elif (cmnd == 'unghost'):
                object.physics.suppress(False)
                if not silent: ki.IAddRTChat(None, 'Successfully de-ghostified %s' % xUserKI.GetObjectName(object), 0)
        return True
# extended object manipulation commands needing arguments
    if (cmnd == 'warp'):
        (valid, data) = xUserKI.GetArg(ki, cmnd, args, 'x coordinate> <y coordinate> <z coordinate> <[list of objects]>|<warp location> <[list of objects]>|<target object> <[list of objects]',
          # manually set location
          lambda args: len(args) >= 3 and xUserKI.IsInt(args[0]) and xUserKI.IsInt(args[1]) and xUserKI.IsInt(args[2]),
          lambda args: ((float(args[0]), float(args[1]), float(args[2])), xUserKI.GetObjects(ki, args[3:], playerList)),
          # used warp point or target object
          lambda args: len(args) >= 1,
          lambda args: (args[0], xUserKI.GetObjects(ki, args[1:], playerList)))
        if not valid or not data[1]: return True
        (location, objects) = data
        if type(location) == type(''): # a warp point or a target object
            try:
                import xUserKIData
                location = xUserKIData.WarpPoints[PtGetAgeName()][location]
            except: # Warp point does not exist, or data module is missing
                object = xUserKI.GetObject(ki, location, playerList)
                if not object: return True
                location = (object.position(), 'to %s' % xUserKI.GetObjectName(object), None) # same format as WarpPoints
        else: # a manually set location
            location = (ptPoint3(location[0], location[1], location[2]), 'to (%1.2f|%1.2f|%1.2f)' % (location[0], location[1], location[2]), None) # same format as WarpPoints
        # warp them
        for object in objects:
            xUserKI.WarpObjectToPos(object, location[0].getX(), location[0].getY(), location[0].getZ())
            if location[2] == True: # disable physics
                object.physics.disable()
            elif location[2] == False: # enable physics
                if not object in xUserKIFlymode.flyingObjects:
                    object.physics.enable()
            if not silent: ki.IAddRTChat(None, 'Warped %s %s' % (xUserKI.GetObjectName(object), location[1]), 0)
        return True
    if (cmnd == 'scale'):
        # determine scale vector - if the first three arguments are numbers, use them for the three dimensions, othewise use only one for all
        (valid, data) = xUserKI.GetArg(ki, cmnd, args, 'scale factor> <[list of objects]>|<scale x> <scale y> <scale z> <[list of objects]',
          # all three dimeniosn defined
          lambda args: len(args) >= 3 and xUserKI.IsFloat(args[1]) and xUserKI.IsFloat(args[2]),
          lambda args: (float(args[0]), float(args[1]), float(args[2]), xUserKI.GetObjects(ki, args[3:], playerList)),
          # only one dimeniosn defined
          lambda args: len(args) >= 1,
          lambda args: (float(args[0]), float(args[0]), float(args[0]), xUserKI.GetObjects(ki, args[1:], playerList)))
        if not valid or not data[3]: return True
        # scale them
        for object in data[3]:
            if object.isAvatar():
                ki.IDoErrorChatMessage('%s is an avatar and can\'t be scaled' % xUserKI.GetObjectName(object))
                continue
            MainMatrix = object.getLocalToWorld()
            scaleMatrix = ptMatrix44()
            scaleMatrix.makeScaleMat(ptVector3(data[0], data[1], data[2]))
            object.netForce(1)
            object.physics.warp(MainMatrix * scaleMatrix)
            if not silent: ki.IAddRTChat(None, 'Scaled %s by (%1.2f|%1.2f|%1.2f)' % (xUserKI.GetObjectName(object), data[0], data[1], data[2]), 0)
        return True
    if (cmnd == 'rot'):
        (valid, data) = xUserKI.GetArg(ki, cmnd, args, 'angle> <[axis (x|y|z)]> <[list of objects]',
          # axis defined
          lambda args: len(args) >= 2 and (args[1] in kAxisNames.keys()),
          lambda args: (float(args[0]), args[1], xUserKI.GetObjects(ki, args[2:], playerList)),
          # axis not defined
          lambda args: len(args) >= 1,
          lambda args: (float(args[0]), 'z', xUserKI.GetObjects(ki, args[1:], playerList)))
        if not valid or not data[2]: return True
        # rotate them
        for object in data[2]:
            rotMatrix = ptMatrix44()
            rotMatrix.makeRotateMat(kAxisNames[data[1]], data[0]/180.0*3.1415926535897932384626)
            object.physics.warp(object.getLocalToWorld() * rotMatrix)
            if not silent: ki.IAddRTChat(None, 'Rotated %s by %d degrees around the %s-axis' % (xUserKI.GetObjectName(object), data[0], data[1]), 0)
        return True
    if (xxConfig.isOffline() and cmnd in ['attach', 'detach']): # this does not seem to be broadcasted via network :( so it's offline only
        (valid, data) = xUserKI.GetArg(ki, cmnd, args, 'parent object> <list of child objects',
          lambda args: len(args) >= 2, lambda args: (xUserKI.GetObject(ki, args[0], playerList), xUserKI.GetObjects(ki, args[1:], playerList)))
        if not valid or not data[0] or not data[1]: return True
        # attach or detach objects
        for object in data[1]:
            if cmnd == 'attach':
                PtAttachObject(object, data[0])
                if not silent: ki.IAddRTChat(None, 'Attached %s to %s' % (xUserKI.GetObjectName(object), xUserKI.GetObjectName(data[0])), 0)
            else:
                PtDetachObject(object, data[0])
                if not silent: ki.IAddRTChat(None, 'Detached %s from %s' % (xUserKI.GetObjectName(object), xUserKI.GetObjectName(data[0])), 0)
        return True
    return False