-- Click to Move: supports basic 4-directional movement with walk and idle animations. -- Author: Thor Alexander -- Created: 12/11/2007 -- -- 01/18/08 JJD Click to move was stealing focus from the chat bar, so I added a quick -- trigger at the end of the function to give focus back. -- 02/02/08 TA Added Turn to Face support for when user clicks on an object when they are standing still. -- 03/01/08 JW Converted to 8 directions system for avatars. -- 04/22/08 JJD Added the target in click to move -- 09/15/08 JW Added arrow key movement. -- 10/08/08 JW Smoothed out movements for both click-terrain and arrow key movement -- 10/16/08 PF Added fix for arrowkey skating issue and dirty, nasty hack at JJD's insistence for thrown emotes -- 10/31/08 PF Added "key" in addition to "state" so that failing to arrowkey path still allows switching to a diagonal -- CONSTANTS -- hacks make me feel dirty THROW_SPEED = 70 THROWN = '11302:5' THROWN_SPRITES = { ['tomato'] = { pointer = '11302:473', sprite = '11302:475', splat = '11302:443' }, ['snowball'] = { pointer = '11302:471', sprite = '11302:476', splat = '11302:444' }, } THROWN_MAX_LIFETIME = 20000 SPLAT_LIFETIME = 2000 Define Properties() dirIndex = 0 dir = 's' avatarId = 1 walk_speed = 4.5 north_state = 0 south_state = 0 west_state = 0 east_state = 0 north_key = 0 south_key = 0 west_key = 0 east_key = 0 last_path_x = 0 last_path_y = 0 in_motion = 0 end Define Commands() MakeInput('Click on terrain to move to destination.', 'mouse-terrain', 'click', 'none', 'path_terrain') MakeCommand('path_terrain', 'Pathfind to terrain.', 'x:float', 'y:float', 'z:float') MakeInput('Press up.', 'up', 'down', 'none', 'press north') MakeInput('Unpress up.', 'up', 'up', 'none', 'unpress north') MakeInput('Press down.', 'down', 'down', 'none', 'press south') MakeInput('Unpress down.', 'down', 'up', 'none', 'unpress south') MakeInput('Press left.', 'left', 'down', 'none', 'press west') MakeInput('Unpress left.', 'left', 'up', 'none', 'unpress west') MakeInput('Press right.', 'right', 'down', 'none', 'press east') MakeInput('Unpress right.', 'right', 'up', 'none', 'unpress east') MakeCommand ('press', 'Press a key.', 'key_name:string') MakeCommand ('unpress', 'Unpress a key.', 'key_name:string') end Command press(key_name) --Debug ('Pressing %s', key_name) state = key_name..'_state' key = key_name .. '_key' self[state] = 1 self[key] = 1 sync_key_states(self) SendTo(self, 'new_arrow_movement', 0, self.x, self.y) end Command unpress(key_name) state = key_name..'_state' key = key_name .. '_key' self[state] = 0 self[key] = 0 sync_key_states(self) SendTo(self, 'new_arrow_movement', 0, self.x, self.y) end Trigger new_arrow_movement(start_x, start_y) -- Debug ('Got to new arrow movement') p = GetPlace() width = p.width height = p.height n = self.north_state s = self.south_state e = self.east_state w = self.west_state -- Debug ('%d %d %d %d', n, s, e, w) new_x = self.x new_y = self.y if n == 1 then new_x = new_x - 1 new_y = new_y - 1 end if s == 1 then new_x = new_x + 1 new_y = new_y + 1 end if e == 1 then new_x = new_x + 1 new_y = new_y - 1 end if w == 1 then new_x = new_x - 1 new_y = new_y + 1 end if new_x > self.x + 1 then new_x = self.x + 1 elseif new_x < self.x - 1 then new_x = self.x - 1 end if new_y > self.y + 1 then new_y = self.y + 1 elseif new_y < self.y - 1 then new_y = self.y - 1 end if (new_x ~= self.x) or (new_y ~= self.y) then --Debug('Attempting a move from %d, %d to %d, %d.', self.x, self.y, new_x, new_y) self.speed = self.walk_speed self.last_path_x = new_x self.last_path_y = new_y PathToLocation(self, new_x, new_y, 2) self.in_motion = 1 else --Debug ('Should be setting speed to 0.') self.speed = 0 self.in_motion = 0 end end Command path_terrain(x,y,z) --[[ locale = GetPlace() if locale.placeId == 1 then return end --]] -- Dirty hack for thrown emotes if (self.chat_emote_throw_object ~= nil) then if (self.chat_emote_throw_object ~= 'none') then local dx = self.x - x local dy = self.y - y local dz = self.z - z local distance = math.sqrt(dx * dx + dy * dy + dz * dz) local time = THROW_SPEED * distance local thrown = CreateObjectById(THROWN, self.x, self.y, self.z) thrown.name = self.chat_emote_throw_object thrown.lifetime = THROWN_MAX_LIFETIME thrown.spriteId = THROWN_SPRITES[self.chat_emote_throw_object].sprite SlideObject(thrown, x, y, z, time, 1) SendTo(self, 'chat_system_splat', time + 250, thrown.id, 0) SendTo(self, 'chat_system_abortthrow', 0) return nil end end self.speed = self.walk_speed self.last_path_x = x self.last_path_y = y PathToLocation(self, x, y, 2) end Trigger path_to(x, y, z) --Debug ('Pathing to %d, %d.', x, y) self.speed = self.walk_speed PathToLocation(self, x, y, 2) end Trigger use(user) PathToLocation(user, self.x-.1, self.y-.1, 2) end Trigger attach() self.dir = 's' self.avatarId = 1 end Trigger path_not_found(x,y) this_object = CreateObjectById("8282:7", self.last_path_x, self.last_path_y) go_here_ui = UiImage(0, "go here", -10, -35, 30, 48, "8282:443") UiAttachUserObject(self, this_object, go_here_ui) UiVisible(go_here_ui, 0, 3000) this_object.lifetime = 3000 self.speed = 0 self.in_motion = 0 self.north_state = 0 self.south_state = 0 self.east_state = 0 self.west_state = 0 SendTo(self, 'new_arrow_movement', 1, x, y) PlayCharacterAnim(self, "idle", self.dir) end Trigger path_end(x,y) if self.north_state == 1 or self.south_state == 1 or self.east_state == 1 or self.west_state == 1 then --Debug ("I think there's a keypress.") SendTo(self, 'new_arrow_movement', 1, x, y) else self.speed = 0 self.in_motion = 0 PlayCharacterAnim(self, "idle", self.dir) end end Trigger path_begin(x,y) if self.north_state == 0 and self.south_state == 0 and self.east_state == 0 and self.west_state == 0 then this_object = CreateObjectById("8282:7", x, y) go_here_ui = UiImage(0, "go here", -10, -35, 30, 48, "8282:72") UiAttachUserObject(self, this_object, go_here_ui) UiVisible(go_here_ui, 0, 3000) this_object.lifetime = 3000 end if self.in_motion == 1 then return end PlayCharacterAnim(self, 'walk', self.dir) self.in_motion = 1 self.speed = self.walk_speed end Trigger facing(degs) --Debug ('Degrees for facing: %d', degs) local newdir = math.ceil((degs/45) + 0.5) if newdir > 8 then newdir = 1 end local dirNames = {'se','s','sw','w','nw','n','ne','e'} last_dir = self.dir self.dir = dirNames[newdir] if self.dir == null then Debug("Unknown direction!!!") return end if last_dir == self.dir then -- Same direction return end SetCharacterDirection(self, self.dir) end function sync_key_states(self) local dir = '' for _, dir in ipairs({'north', 'south', 'east', 'west'}) do self[dir .. '_state'] = self[dir .. '_key'] end end