$include "../defaults.icn" link "../utilities" # # class: avatar # # a super class for every avatar model # class avatar() abstract method render() abstract method derender() abstract method actions(action_name, option) abstract method move(x,y,z,angle) abstract method movePartComplex(part_name,x,y,z) abstract method parser(avatar_name) end # class avatar global Objects global currObjsID # # Class: avatron # This is a class that renders a humanoid avatar # The (origx, origy, origz) is located at the intersection # of the neck and body. # class avatron : avatar (origx, origy, origz, sex, angle,ro,mv,h,b,c,la,ra,lg,rg,face, X,Y,Z,xsize,ysize,zsize,height,color, face_path, a_name, scolor, # Shirt color pcolor, # Pants color shcolor, # Shoes color hdchoice, ps, moveuid, moveuidbody, # from the OLD avatar class uid, x, y, z, # avatar's coordinates lx, lz, # in view mode 2 fint, rarm, larm, grouping, render_set, isRendered, vertical_ptr,horizontal_ptr, # angles for pointing isPointing, object, chair, sittingDown, body_part, currObjID ) method initialize() face_path:= world.avatar_path parser( world.avatar_path || uid || ".avt") setup( x, y, z, angle) end method derender() local len, i, item, win3d, dispList # If room is not rendered then return #Use WSection function to skip this list from rendering if (\h.headWS) then{ h.headWS.skip:=1 b.bodyWS.skip:=1 la.armWS.skip:=1 ra.armWS.skip:=1 lg.legWS.skip:=1 rg.legWS.skip:=1 } # If room is not rendered then return if /(isRendered) then return isRendered := &null world.NeedsRefresh() return end # method derender() # # flush pending net output # method flushnet() if session.isUp() then { session.Write(grouping) grouping := list() } end # # move_part(Name, Dir, Angle) # Purpose: to move a particular body part # Parameters: Name - name of the part to be moved # Dir - direction in which it is to move # Angle - angle for which it is to be rotated # method move_part(name, dir, ang) case name of { "right_arm" : ra.setAngle(ang, dir) "left_arm" : la.setAngle(ang, dir) "right_leg" : rg.setAngle(ang, dir) "left_leg" : lg.setAngle(ang, dir) } world.NeedsRefresh() if (self === world.nsh_dialog.avatar) & session.isUp() then { put(grouping, moveuid || "part " || name || " " || dir || " " || ang) } end # # move_part_complex(name,x,z) # Purpose: to move a body part in x,z direction freely # USED for pointing # Parameters: name - name of the body part to be moved # x - angle along the x-axis # z - angle along the z-axis # method move_part_complex(name,x,y,z) local msg case name of { "right_arm" : ra.setAngleComplex(x,y,z) "head" : h.setAngleComplex(x,y,z) "left_arm" : la.setAngleComplex(x,y,z) "right_leg" : rg.setAngleComplex(x,y,z) "left_leg" : lg.setAngleComplex(x,y,z) } world.NeedsRefresh() if (self === world.nsh_dialog.avatar) & session.isUp() then { msg := moveuid || "part2 " || name || " " || x || " " || y || " " ||z put(grouping, msg) } end # # move(X,Y,Z,angle) # Purpose: to move the avatar # Parameters: [X,Y,Z] - current x, y, z coordinates # Angle - angle in which the avatar should be turned # method move(posx,posy,posz,ang) local degree degree := rtod(ang) # use internal fn for conversion if /ro then fail ro.angle:=degree # update the angle of rotation matrix (e.g. ro) X := posx Y := origy+2*height # posy Z := posz mv.x := X mv.y := Y mv.z := Z if *object > 0 then object[currObjID].moveAlongAvatar(mv.x,posy,mv.z,degree) # view_mode 2 - over shoulder - is too jerky - this fixes it if world.cam.view_mode = 2 then { world.NeedsRefresh() } end # # sets avatar talking state to true # method isTalking() h.isTalking() if (self === world.nsh_dialog.avatar) & session.isUp() then { put(grouping, moveuid || "mouth") } end # # sets avatar talking state to state="ON" or "OFF" # method SetTalkState(state) h.SetTalkState(state) if (self === world.nsh_dialog.avatar) & session.isUp() then { put(grouping, moveuid || "mouth") } end # # setup() # Purpose: to set up each part of avatar by instantiating # the body part # method setup(x,y,z,ang) X:=x;Y:=y;Z:=z;angle:=ang h := head() b := body() la := arm() ra := arm() lg := leg() rg := leg() end # # render() # Purpose: to render graphics of each part thus a whole # avatar # method render() local oldwin if \isRendered then return isRendered := 1 oldwin := &window &window := !gui::dispatcher.subwins actual_render() &window := oldwin end # # actual_render() depends on &window being set to the subwindow # method actual_render() local S PushMatrix() height := 0.5 mv:=Translate(X , origy+2*height , Z ) ro:=Rotate(angle,0,1,0) Scale(xsize, height, zsize) h.render(face_path || face, color, hdchoice) b.render(a_name, scolor, sex, pcolor, face_path, ps) la.render("l", color, scolor) ra.render("r", color, scolor) lg.render("l", pcolor, shcolor) rg.render("r", pcolor, shcolor) PopMatrix() WAttrib("texmode=on") end # # parse(File) # Purpose: Takes a file and parse each line and set them to their # appropriate variables # method parser(file_name) local line, file, i, nm, val file:= open(file_name) | stop("Can't open ", file_name) while line := trim(read(file)) do { if line[1]~=="#" then { if not (i := find("=", line) + 1) then { write("avt file format error in ", image(line)) break } nm := map(line[1:i-1]) if *(val := line[i:0]) = 0 then break case nm of { "name": a_name := val "gender": sex := val "skin color": color := val "shirt color": scolor := val "pants color": pcolor := val "shoes color": shcolor := val "head shape": hdchoice := val "face picture": face := val default : self[nm] := val } } } close(file) end # # getcolor() # # This returns the color of the avatar, when invoked. # method getcolor() return color end $define MINDELTA 0.08 method test_new_pos(step,deltax, deltaz,y,mov) local olddeltax := deltax, olddeltaz := deltaz, room, rdl, typ room := world.curr_room # rdl means "room disallows list" if (rdl := room.disallows(x+deltax,z+deltaz,y)) & (/(rdl|rdl[1])) then { deltax := 0 if rdl := room.disallows(x,z+deltaz,y) & (/(rdl|rdl[1])) then { deltaz := 0 deltax := olddeltax if rdl := room.disallows(x+deltax,z,y) & (/(rdl|rdl[1])) then { # try a smaller move if abs(deltax|deltaz) > MINDELTA then return test_new_pos(step,deltax*0.8,deltaz*0.8,y,mov) fail } } } typ := (\rdl)[1] if mov = (1|3|4) then { if /typ then return [x+deltax, z+deltaz, room.y] else if typ = 1 then return [x+deltax,z+(deltaz),y+(0.33*deltaz)] else if typ = 2 then return [x+(deltax),z+deltaz,y+(0.33*deltax)] else if typ = 3 & y < 1 then { y := 1 return [x+deltax,z+deltaz,y] } else if typ=3 & y=1 then return [x+deltax,z+deltaz,y] else if typ = 4 then { return [x+(rdl[2]/5.0),z+deltaz,y+(rdl[3]/5.0)] } } else { if /typ then return [x+deltax,z+deltaz,room.y] if typ = 1 then return [x+deltax,z+(deltaz),y+(0.33*deltaz)] if typ = 2 then return [x+(deltax),z+deltaz,y+(0.33*deltax)] if y >= 1 & typ = 3 then return [x+deltax,z+deltaz,y] if y < 1 & typ = 3 then return [x,z+deltaz,y+1] } end # method test_new_pos(step, deltax, deltaz) # local olddeltax := deltax, olddeltaz := deltaz, room # room := world.curr_room # if room.disallows( x+deltax, z+deltaz ) then { # deltax := 0.0 # if room.disallows( x+deltax, z+deltaz ) then { # deltaz := 0.0 # deltax := olddeltax # if room.disallows(x+deltax, z+deltaz) then { # # try a smaller move # if abs(deltax|deltaz) > MINDELTA then # return test_new_pos(step, deltax*0.8, olddeltaz*0.8) # fail # } # } # } # return [x+deltax, z+deltaz] # end method moveabs(nx,ny,nz,na) x := nx y := ny z := nz angle := na move(nx, ny, nz, na) if self === world.nsh_dialog.avatar then { if world.cam.view_mode > 1 then { cam_follows() # avatar==cam } broadcast_move() } else world.NeedsRefresh() end method actions(act, step ) local deltax, deltaz, newpos case act of { "move_forward": { # # move FORWARD # lx := sin(angle) lz := cos(angle) deltax := step * lx deltaz := step * lz # write("move(1,",step,") viewmode ", world.cam.view_mode) # # ask test_new_pos if we can move where we want. # if it succeeds, it returns our new [x, z] location. # either deltax or deltaz may get dropped if out of bounds. # if newpos := test_new_pos( step, deltax, deltaz,y,1 ) then { x := newpos[1] z := newpos[2] y := newpos[3] # world.nsh_dialog.image_5.movearrow(a_name,x,y,z) if \ro then move(x, y, z, angle) if self === world.nsh_dialog.avatar then { if world.cam.view_mode > 1 then { #write("cam follows move") cam_follows() # avatar==cam } broadcast_move() } else { # need to not refresh for every single avatar move world.NeedsRefresh() } if fint < 3 then { if rarm = 0 & isPointing = 0 then { move_part("right_arm", "fb", 10) } move_part("left_leg", "fb", 10) if larm = 0 then { move_part("left_arm", "fb", -10) } move_part("right_leg", "fb", -10) fint +:= 1 } else { if rarm = 0 & isPointing = 0 then { move_part("right_arm", "fb", -10) } move_part("left_leg", "fb", -10) if larm = 0 then { move_part("left_arm", "fb", 10) } move_part("right_leg", "fb", 10) fint +:= 1 if fint = 6 then { fint:=0 } } } } "move_pointer_up" : { if isPointing = 1 then { if vertical_ptr > 210 then vertical_ptr:=vertical_ptr-1 move_part_complex("right_arm", vertical_ptr, 0, horizontal_ptr) move_part_complex("head", vertical_ptr-270, horizontal_ptr, 0) } } "move_backward" : { # # move BACKWARD - moon-walk style # lx := sin(angle) lz := cos(angle) deltax := step * lx deltaz := step * lz # write("avatar move x,y,z, angle ",x," ",y," ",z," ",angle) if newpos := test_new_pos( step, deltax, deltaz,y,2 ) then { x := newpos[1] z := newpos[2] y :=newpos[3] move(x, y, z, angle) if fint < 3 then { if rarm = 0 & isPointing = 0 then { move_part("right_arm", "fb", 10) } move_part("left_leg", "fb", 10) if larm = 0 then { move_part("left_arm", "fb", -10) } move_part("right_leg", "fb", -10) fint +:= 1 } else { if rarm = 0 & isPointing = 0 then { move_part("right_arm", "fb", -10) } move_part("left_leg", "fb", -10) if larm = 0 then { move_part("left_arm", "fb", 10) } move_part("right_leg", "fb", 10) fint +:= 1 if fint = 6 then { fint:=0 } } if self === world.nsh_dialog.avatar then { if world.cam.view_mode > 1 then { cam_follows() # avatar == cam } broadcast_move() } } } "move_pointer_down" : { if isPointing = 1 then { if vertical_ptr < 330 then vertical_ptr:=vertical_ptr+1 move_part_complex("right_arm", vertical_ptr, 0, horizontal_ptr) move_part_complex("head", vertical_ptr-270, horizontal_ptr, 0) } } "raise_right_arm" : { # # Raising Right Arm # isPointing := 1 move_part_complex("right_arm",0,0,0) move_part_complex("head",0,0,0) if rarm = 0 then { rarm:=1 move_part("right_arm", "fb", -180, 1) } else { rarm:=0 move_part("right_arm", "fb", 10, 1) } } # end case 3 "raise_left_arm" : { # # Raising Left Arm # if larm = 0 then { larm:=1 move_part("left_arm", "fb", -180, 1) # -10 ? } else { larm:=0 move_part("left_arm", "fb", 10, 1) } } # end case 4 "move_right" : { # # move SIDEWAY-right # # x := x - sin(1.571-angle)*0.1 # z := z + cos(1.571-angle)*0.1 # should these be updated ??? # lx := sin(1.571-angle) # lz := cos(1.571-angle) deltax := step * ( -sin(1.571-angle) ) deltaz := step * ( cos(1.571-angle)) # write("avatar move x,y,z, angle ",x," ",y," ",z," ", angle) if newpos := test_new_pos( step, deltax, deltaz,y,3 ) then { x := newpos[1] z := newpos[2] y :=newpos[3] lx +:= deltax lz +:= deltaz if fint < 3 then { move_part("right_leg", "s", -10) move(x, y, z, angle) if self === world.nsh_dialog.avatar then { if world.cam.view_mode > 1 then { cam_follows() #avatar==cam } broadcast_move() } fint +:= 1 } else { move_part("right_leg", "s", 0) fint +:= 1 if fint = 6 then { fint:=0 } } } } "move_pointer_right" : { if isPointing = 1 then { if horizontal_ptr > -30 then horizontal_ptr:=horizontal_ptr-1 move_part_complex("right_arm", vertical_ptr, 0, horizontal_ptr) move_part_complex("head", vertical_ptr-270, horizontal_ptr, 0) } } # end case 5 "move_left" : { # # move SIDEWAY-left # # x := x + sin(1.571-angle)*0.1 # z := z - cos(1.571-angle)*0.1 deltax := step * ( sin(1.571-angle)) deltaz := step * ( -cos(1.571-angle)) # write("avatar move x,y,z, angle ",x," ",y," ",z," ", angle) if newpos := test_new_pos( step, deltax, deltaz,y,4) then { x := newpos[1] z := newpos[2] y := newpos[3] lx +:= deltax lz +:= deltaz if fint < 3 then { move_part("left_leg", "s", 10) move( x, y, z, angle) if self === world.nsh_dialog.avatar then { if world.cam.view_mode > 1 then { #write("cam follows move6") cam_follows() # avatar == cam } broadcast_move() } fint +:= 1 } else { move_part("left_leg", "s", 0) fint +:= 1 if fint = 6 then { fint:=0 } } } } "move_pointer_left" : { if isPointing = 1 then { if horizontal_ptr < 30 then horizontal_ptr:=horizontal_ptr+1 move_part_complex("right_arm", vertical_ptr, 0, horizontal_ptr) move_part_complex("head", vertical_ptr-270, horizontal_ptr, 0) } } # end case 6 "turn_left" : { # # turn LEFT # #if isPointing=0 then { angle +:= step if abs(angle) > 2 * &pi then angle := 0.0 move( x, y, z, angle) if self === world.nsh_dialog.avatar then { if world.cam.view_mode > 1 then { #write("cam follows move7") cam_follows() # avatar == cam } broadcast_move() } #} #else { # if horizontal_ptr < 30 then # horizontal_ptr:=horizontal_ptr+1 # move_part_complex("right_arm", vertical_ptr, 0, # horizontal_ptr) # move_part_complex("head", vertical_ptr-270, # horizontal_ptr, 0) #} } # end case 7 "turn_right" : { # # turn RIGHT # #if isPointing=0 then { angle -:= step if abs(angle) > 2 * &pi then angle := 0.0 move( x, y, z, angle) if self === world.nsh_dialog.avatar then { if world.cam.view_mode > 1 then { #write("cam follows move8") cam_follows() # avatar == cam } broadcast_move() } #} #else { # if horizontal_ptr > -30 then # horizontal_ptr:=horizontal_ptr-1 # move_part_complex("right_arm", vertical_ptr, 0, # horizontal_ptr) # move_part_complex("head", vertical_ptr-270, # horizontal_ptr, 0) #} } # end case 8 # # back to NORMAL # "back_default" : { move_part_complex("head", 0, 0, 0) move_part_complex("body", 0, 0, 0) move_part_complex("right_arm", 0, 0, 0) move_part_complex("left_leg", 0, 0, 0) move_part_complex("left_arm", 0, 0, 0) move_part_complex("right_leg", 0, 0, 0) } # # pointing # "toggle_pointer" : { if isPointing=0 then { # Everything goes back to normal move_part("right_arm", "fb", 0) move_part("left_leg", "fb", 0) move_part("left_arm", "fb", 0) move_part("right_leg", "fb", 0) vertical_ptr:=270 horizontal_ptr:=0 move_part("right_arm", "fb", 270) isPointing:=1 } else { move_part_complex("right_arm",0,0,0) move_part_complex("head",0,0,0) isPointing:=0 } } "toggle_talk": { isTalking() world.NeedsRefresh() } "set_talk_on":{ SetTalkState("ON") world.NeedsRefresh() } "set_talk_off":{ SetTalkState("OFF") world.NeedsRefresh() } "possess" : { if \step then { possess(step)} step:=&null } "unpossess" : { if \step then { # write("calling unpossess") unpossess(step) } else #write("No object is found") step:=&null } "switchObjectUp" : { if /step then { #write("calling switchObjUp method") switchObjectUp() } } "switchObjectDown" : { if /step then { # write("calling switchObjDown method") switchObjectDown() } } } # end case flushnet() end # method actions() method possess(object1) local ownedObj,objCol if *object > 0 then { self.object[currObjID].deRender() case self.object[currObjID].getPlacedAt() of { "hand" : { la.unpossess()} "back" : { b.unpossess() } } } currObjID := currObjID + 1 #write(" CURROBJID = ",currObjID) put(self.object,object1) self.object[currObjID].owner:=name self.object[currObjID].possessed:=1 move_part("right_arm", "fb", 0) move_part("left_leg", "fb", 0) move_part("left_arm", "fb", 0) move_part("right_leg", "fb", 0) if (self === world.nsh_dialog.avatar) & session.isUp() then { put(grouping, "\\possess " || self.object[currObjID].Id || " " || a_name || " " || world.curr_room.name) } self.object[currObjID].setSize(xsize,height,zsize) self.object[currObjID].setPosAvatar(x,y,z,angle) #self.object[currObjID].mov.x := x #self.object[currObjID].mov.y := 1.5 #self.object[currObjID].mov.z := z # self.object[currObjID].rot.angle := angle Objects := object currObjsID := currObjID move(x,y,z,angle) if *object > 0 then { case object[currObjID].getPlacedAt() of { "hand" : { la.possess(object[currObjID])} "back" : { b.possess(object[currObjID]) } } } #write(" CURROBJID = ",currObjID) ownedObj := object[currObjID].name objCol := object[currObjID].color world.nsh_dialog.write_to_chat_win( a_name, " possessed a ",objCol," color ", ownedObj) #write(" x,y,z ",self.object[currObjID].x || " " || self.object[currObjID].y || " " || self.object[currObjID].z) # write(" x,y,z ",self.object[currObjID].mov.x || " " || self.object[currObjID].mov.y || " " || self.object[currObjID].mov.z) #write(" x,y,z ",self.object[currObjID].mv.x || " " || self.object[currObjID].mv.y || " " || self.object[currObjID].mv.z) # write(" x,y,z ",self.object[currObjID].mvDraw.x || " " || self.object[currObjID].mvDraw.y || " " || self.object[currObjID].mvDraw.z) end method unpossess() local i,ownedObj,objCol,flag flag := 0 if *object > 0 then { #write("entered unpossess") object[currObjID].unpossessed(x,y,z) object[currObjID].possessed:=0 ownedObj := object[currObjID].name objCol := object[currObjID].color world.nsh_dialog.write_to_chat_win( a_name, " unpossessed a ",objCol," color ", ownedObj) case object[currObjID].getPlacedAt() of { "hand" : { la.unpossess()} "back" : { b.unpossess() } } if (self === world.nsh_dialog.avatar) & session.isUp() then { put(grouping, "\\unpossess " || self.object[currObjID].Id || " " || a_name) } i:=currObjID while i < *object do { object[i]:=&null object[i]:=object[i+1] object[i].possessed := 1 i+:=1 } if currObjID > 0 then currObjID := currObjID - 1 #write("currObjID = ",currObjID) object[i] := &null pull(object) object[currObjID].reRender(world.curr_room.render_level) case object[currObjID].getPlacedAt() of { "hand" : { la.possess(object[currObjID])} "back" : { b.possess(object[currObjID]) } } currObjsID := currObjsID Objects := object move(x,y,z,angle) /object := [] } end method switchObjectUp() local switchFrom,switchTo,switchFromCol,switchToCol if currObjID < *object then { # write("called next method") move_part("right_arm", "fb", 0) move_part("left_leg", "fb", 0) move_part("left_arm", "fb", 0) move_part("right_leg", "fb", 0) case self.object[currObjID].getPlacedAt() of { "hand" : { la.unpossess()} "back" : { b.unpossess() } } object[currObjID].deRender() if (self === world.nsh_dialog.avatar) & session.isUp() then { put(grouping, "\\switchobjectup " || self.object[currObjID].Id || " " || a_name) } currObjID:=currObjID+1 object[currObjID].reRender(world.curr_room.render_level) switchFrom := object[currObjID-1].name switchFromCol := object[currObjID-1].color switchTo := object[currObjID].name switchToCol := object[currObjID].color world.nsh_dialog.write_to_chat_win( a_name, " switched from " , switchFromCol," color ", switchFrom, " to ", switchToCol, " color ", switchFrom) case object[currObjID].getPlacedAt() of { "hand" : { la.possess(object[currObjID])} "back" : { b.possess(object[currObjID]) } } currObjsID := currObjID move(x,y,z,angle) } end method switchObjectDown() local switchFrom,switchTo,switchFromCol,switchToCol if currObjID > 1 then { #write("called prev method") move_part("right_arm", "fb", 0) move_part("left_leg", "fb", 0) move_part("left_arm", "fb", 0) move_part("right_leg", "fb", 0) case self.object[currObjID].getPlacedAt() of { "hand" : { la.unpossess()} "back" : { b.unpossess() } } object[currObjID].deRender() if (self === world.nsh_dialog.avatar) & session.isUp() then { put(grouping, "\\switchobjectdown " || self.object[currObjID].Id || " " || a_name) } currObjID:=currObjID-1 switchFrom := object[currObjID+1].name switchFromCol := object[currObjID+1].color switchTo := object[currObjID].name switchToCol := object[currObjID].color world.nsh_dialog.write_to_chat_win( a_name, " switched from ", switchFromCol," color ", switchFrom, " to ", switchToCol, " color ", switchFrom) object[currObjID].reRender(world.curr_room.render_level) case object[currObjID].getPlacedAt() of { "hand" : { la.possess(object[currObjID])} "back" : { b.possess(object[currObjID]) } } currObjsID := currObjID move(x,y,z,angle) } end method getX() return x#+la.getX() end method getY() return y#+la.getY() end method getZ() return z#+la.getZ() end method getName() return name end method cam_follows() local adj_angle, r, owcy if world.cam.view_mode = 3 then { r := h.headr owcy := world.cam.y - world.cam.looky world.cam.x := x + r * sin(angle) * .6 # should modify hardwired 1.5's here and below to relate to avatar height world.cam.y := y + 1.5 world.cam.z := z + r * cos(angle) * .6 world.cam.lx := lx world.cam.lz := lz world.cam.lookx := x + 4 * sin(angle) world.cam.looky := y + 1.5 - owcy world.cam.lookz := z + 4 * cos(angle) return } if world.cam.view_mode = 2 then { # camera over shoulder adj_angle := angle + dtor(210.0) if adj_angle > 2 * &pi then { adj_angle -:= 2 * &pi } if adj_angle < -2 * &pi then { adj_angle +:= 2 * &pi } lx := sin( adj_angle ) lz := cos( adj_angle ) world.cam.x := (x + 2.4 * lx ) world.cam.y := y + 0.2 + 1.5 world.cam.z := (z + 2.4 * lz ) while not world.curr_room.isinside(world.cam.x, world.cam.z) do { lx *:= 0.9; lz *:= 0.9 world.cam.x := (x + 2.4 * lx ) world.cam.y := y world.cam.z := (z + 2.4 * lz ) } world.cam.lookx := x - lx / (world.cam.looky) := y + 1.5 world.cam.lookz := z - lz world.cam.eye() return } end # method cam_follows() # now called from avatar.move() # maybe this should be moved to move???? # ###### cannot seem to access field uid from there - very strange method broadcast_move() local msg msg := moveuidbody || trncReal(x) || " " || trncReal(y) || " " || trncReal(z) || " " || trncReal(angle) put(grouping, msg) # WSync() end initially(uid_in, x_in, y_in, z_in, ang) #face_path_in) scolor:="red" pcolor:="red" shcolor:="red" a_name:="guest" X:= 0 Y:= 0 Z:= 0 xsize:=0 ysize:=0 zsize:=0 height:= 0 origx := 0 origy := 0 origz := 0 sex := "m" face_path := &null #face_path_in face := "smily.gif" hdchoice:=1 $ifdef _UNIX ps := "/" $else ps := "\\" $endif # from the OLD avatar class uid := uid_in moveuid := "\\move " || uid || " " moveuidbody := moveuid || "body " x := x_in # avatar's cooridinates y := y_in # previously named origx, origy, origx z := z_in lx := 0.0 lz := 0.0 angle := ang #aky # avatar orientation angle # previously named cam_angle fint := 0 rarm := 0 larm := 0 render_set := set() # capture display list elts for \delavatar isRendered := &null grouping := list() isPointing:=0 vertical_ptr:=0 horizontal_ptr:=0 # angles for pointing # for object interactions /object:=[] # object list chair:=&null # chair to sit on sittingDown:=0 body_part := "" position := "" /currObjID:=0 /Objects := [] /currObjsID := 0 end # # Class: head # This class just renders head and neck # class head : avatarParts( headx,heady,headz,headr, # Head coodinate, radius of the head neckx,necky,neckz,neckh,neckt,neckb, # Neck coor. and other info. on neck m1,m2,m3,m4, # stuff for talking effect counter, ch, romx,romy, romz, # rotation matrix for x and z axis headWS ) method render(face, color, choice) local f, n, tmp, txcoords, coords, sz,win3d ch:=choice win3d := !gui::dispatcher.subwins headWS := WSection(win3d, "head") if map(color[-4:0]) == ".gif" then every WAttrib("texmode=on","texture="||color) else { WAttrib("texmode=off") Fg(color) } DrawCylinder(neckx, necky, neckz, neckh,neckt,neckb) # Egg Shape or Putting picture on a box if choice == 2 then { PushMatrix() initRMatrix() WAttrib("texmode=on") if not WAttrib("texture="||face) then WAttrib("texture=dat/avatars/guest.gif") WAttrib("texcoord=auto") Rotate(270,1,0,0) Scale(1,1,1.2) PushMatrix() Translate(headx,0,0.55) DrawSphere(0, 0, 0, headr) WAttrib("texmode=off") Fg("red") Rotate(90,1,0,0) DrawCylinder(-headx,-heady+heady*0.7,0,0.03,0.01,0.01) DrawCylinder(-headx,-heady+heady*0.7,0,0.05,0.015,0.015) DrawCylinder(-headx,-heady+heady*0.7,0,0.08,0.02,0.02) DrawCylinder(-headx,-heady+heady*0.7,0,0.12,0.03,0.03) PopMatrix() PopMatrix() } else { PushMatrix() Translate(headx, heady, headz) initRMatrix() DrawSphere(0,0,0, headr) # Face cube txcoords := [0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0 ] tmp := txcoords[1] || "," || txcoords[2] || "," || txcoords[3] || "," tmp := tmp || txcoords[4] || "," || txcoords[5] || "," || txcoords[6] || "," tmp := tmp || txcoords[7] || "," || txcoords[8] sz := headr*1.3 / 2.0 coords := [ 0 , 0, 0, 0 , 2 * sz, 0, 2* sz , 2 * sz, 0, 2* sz , 0, 0 ] # Face polygon # formerly a cube PushMatrix() Translate( -sz, -heady/2, headr ) every WAttrib("texmode=on", "texture="|| face , "texcoord="||tmp) FillPolygon ! coords WAttrib("texmode=off") PopMatrix() Fg("red") DrawCylinder(-headx,-heady+heady*0.7,0,0.03,0.01,0.01) DrawCylinder(-headx,-heady+heady*0.7,0,0.05,0.015,0.015) DrawCylinder(-headx,-heady+heady*0.7,0,0.08,0.02,0.02) DrawCylinder(-headx,-heady+heady*0.7,0,0.12,0.03,0.03) PopMatrix() } WAttrib("texmode=off") WSection(win3d) end method isTalking() if /m1 then fail if /m2 then fail if /m3 then fail if /m4 then fail if counter=0 then { #m1.z:=0.5 #m2.z:=0.55 #m3.z:=0.6 #m4.z:=0.68 SetTalkState("ON") counter:=1 } else { #m1.z:=0 #m2.z:=0 #m3.z:=0 #m4.z:=0 SetTalkState("OFF") counter:=0 } end method SetTalkState(state) # state can be "ON" or "OFF" if /m1 then fail if /m2 then fail if /m3 then fail if /m4 then fail if state === "ON" then { m1.z:=0.5 m2.z:=0.55 m3.z:=0.6 m4.z:=0.68 } else{ # if state === "OFF" m1.z:=0 m2.z:=0 m3.z:=0 m4.z:=0 } end initially() counter:=0 ch:=1 headx := 0 heady := 0.6 headz := 0 headr := 0.5 neckx := 0 necky := 0 neckz := 0 neckh := 0.3 neckt := 0.1 neckb := 0.1 end # # Class: body # This class just renders the body # class body : avatarParts( bodyx,bodyy,bodyz,bodyh,bodyt,bodyb, chestx,chesty,chestz,chestr,bodyWS ) method render(name, scolor, sex, pcolor, letter_path, ps) local win3d win3d := !gui::dispatcher.subwins bodyWS := WSection(win3d, "body") PushMatrix() Scale(1,1,0.7) PushMatrix() if map(pcolor[-4:0]) == ".gif" then every WAttrib("texmode=on","texture="||pcolor) else { WAttrib("texmode=off") Fg(pcolor) } Translate(0,-bodyh,0) Scale(1,0.5,1) DrawSphere(0,0,0,bodyt-0.01) PopMatrix() if map(scolor[-4:0]) == ".gif" then every WAttrib("texmode=on","texture="||scolor) else { WAttrib("texmode=off") Fg(scolor) } PushMatrix() Scale(1,0.1,1) DrawSphere(0,0,0,bodyb) PopMatrix() DrawCylinder(0, -bodyh, 0, bodyh, bodyt, bodyb) if sex == "w" then { PushMatrix() Translate(0,chesty,chestz) DrawSphere(chestx,0,0, chestr) DrawSphere(-chestx,0,0, chestr) PopMatrix() createNameTag(name,0.8,0,-bodyh+0.15,0.51, letter_path, ps) } else createNameTag(name,0.8,0,-bodyh+0.6,0.51, letter_path, ps) PopMatrix() WSection(win3d) end initially() bodyx := 0 bodyy := 0 bodyz := 0 bodyh := 0.9#1.0 bodyt := 0.45 bodyb := 0.5 chestx := 0.175 chesty := -0.3 chestz := 0.3 chestr := 0.3 end # # Class: arm # This class renders the left arm and hand and shoulder # class arm : avatarParts ( sholdx,sholdy,sholdz,sholdr, # Shoulder armx,army,armz,armh,armt,armb, # Arm handx,handy,handz,handr, # Hand armWS ) # # render # Purpose: to render the left arm of the avatar # method render(side,color,scolor) local win3d win3d := !gui::dispatcher.subwins armWS := WSection(win3d, "arm") PushMatrix() if side == "l" then Translate(sholdx,sholdy,sholdz) else Translate(-sholdx,sholdy,sholdz) initRMatrix() if map(scolor[-4:0]) == ".gif" then every WAttrib("texmode=on","texture="||scolor) else { WAttrib("texmode=off") Fg(scolor) } PushMatrix() Scale(1.34,1,1) if side == "l" then DrawSphere(-0.1,-0.05,0, sholdr+0.08) else DrawSphere(0.1,-0.05,0, sholdr+0.08) PopMatrix() if map(color[-4:0]) == ".gif" then every WAttrib("texmode=on","texture="||color) else { WAttrib("texmode=off") Fg(color) } DrawCylinder(0, -armh, 0, armh, armt, armb) DrawSphere(0, -handy, 0, handr) # Chicken finger if side == "r" then { DrawCylinder(0.1,-handy-0.25,0.08,0.25,0.06,0.06) DrawSphere(0.1,-handy-0.25,0.08,0.06) } PopMatrix() WSection(win3d) end method getX() return sholdx end method getY() return -handy end method getZ() return sholdz end method possess(object1) self.object:=object1 . object.setPosPart(sholdx-0.15,0,sholdz-0.04) #object.setPosPart(sholdx-0.15,sholdy,sholdz) #object.setPosObj(0,0,0) object.setPosObj(0,0.47,0) #object.render() end method unpossess() object:=&null end initially() sholdx := 0.6#0.7 sholdy := -0.1 sholdz := 0 sholdr := 0.12#0.26#0.3 armx := 0.7 army := -0.05 armz := 0 armh := 1.1#1.2 armt := 0.12#0.15 armb := 0.12#0.15 handx := armx handy := (army+armh)*0.95 handz := armz handr := 0.21#0.24 end # # Class: leg # This class renders left hip, leg, and foot # Please, refer to left_arm method for information # class leg : avatarParts ( hipx,hipy,hipz,hipr, # Hip legx,legy,legz,legh,legt,legb, # Leg feetx,feety,feetz,feetir,feetor, # Feet rot,legWS ) method render(side,pcolor,shcolor) local win3d win3d := !gui::dispatcher.subwins legWS := WSection(win3d, "leg") PushMatrix() if side == "l" then Translate(hipx,-hipy,hipz) else Translate(-hipx,-hipy,hipz) initRMatrix() if map(pcolor[-4:0]) == ".gif" then every WAttrib("texmode=on","texture="||pcolor) else { WAttrib("texmode=off") Fg(pcolor) } DrawCylinder(0,-legh, 0, legh, legt, legb) PushMatrix() Translate(0,-legh,0) rot:=Rotate(0,1,0,0) DrawSphere(0,0,0,legt) DrawCylinder(0,-legh,0,legh,legt,legb) if map(shcolor[-4:0]) == ".gif" then every WAttrib("texmode=on","texture="||shcolor) else { WAttrib("texmode=off") Fg(shcolor) } PushMatrix() Translate(0,-legh,0.08) Scale(1,0.5,1.6) DrawSphere(0,0,0,0.2) PopMatrix() PopMatrix() WSection(win3d) end method incrementAngle() rot.angle:=rot.angle+1 end method decrementAngle() rot.angle:=rot.angle-1 end method setAnglePart(ang) rot.angle:=ang end initially() hipx := 0.25 hipy := 0.95 hipz := 0 hipr := 0.195#0.23 legx := hipx legy := hipy legz := hipz legh := 0.85/2 legt := hipr*0.7 legb := hipr*0.7 feetx := legx feety := legy+legh feetz := legz feetir := 0.13 feetor := 0.2 end class avatarParts (ps, romx, romy, romz, #rotation matrix for setAngleComplex() object,nameTagWS ) method initRMatrix() romx:=Rotate(0,0,0,0) romy:=Rotate(0,0,0,0) romz:=Rotate(0,0,0,0) end method setAngleComplex(xangle, yangle, zangle) #if *Objects > 0 then { Objects[currObjsID].moveAlongPart(xangle,yangle,zangle) #} if /romx then fail if /romy then fail if /romz then fail romx.angle:=xangle romy.angle:=yangle romz.angle:=zangle romx.x:=1 romx.y:=0 romx.z:=0 romy.x:=0 romy.y:=1 romy.z:=0 romz.x:=0 romz.y:=0 romz.z:=1 end # # setAngle (Angle, Dir) # Purpose: to move the arm and hand # method setAngle(angle, dir) # # fb stands for forward-back # s stands for side-side # if /romx then fail if /romy then fail if /romz then fail if dir == "fb" then { if *Objects > 0 then { Objects[currObjsID].moveAlongPart(angle,0,0) } romx.angle:=angle # set the angle romx.x:=1 # update the angle of the arm romx.y:=0 # to be rotated by; along X- romx.z:=0 # axis } else if dir == "s" then { if *Objects > 0 then Objects[currObjsID].moveAlongPart(0,0,angle) romz.angle:=angle # set the angle romz.x:=0 # update the angle of the arm romz.y:=0 # along Z-axis romz.z:=1 } end method createNameTag(name,len,x,y,z, letter_path, ps) local i, txcoords, tmp, interval, ls, coords, S, ch,win3d i:=0 ls:=len/*name interval:=-(x+len/2) WAttrib("texmode=off") while i < *name do { txcoords := [0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0 ] tmp := txcoords[1] || "," || txcoords[2] || "," || txcoords[3] || "," || txcoords[4] || "," || txcoords[5] || "," || txcoords[6] || "," || txcoords[7] || "," || txcoords[8] coords := [ 0 , 0 , 0, 0 , ls, 0, ls, ls, 0, ls, 0 , 0 ] PushMatrix() Translate(interval,y,z) ch := map(name[i+1],&lcase,&ucase) every WAttrib("texmode=on","texture="||letter_path|| "letters"||ps||ch||".GIF", "texcoord="||tmp) FillPolygon ! coords WAttrib("texmode=off") DrawCube(ls/2,ls/2,-ls/2-0.001,ls) PopMatrix() interval:=interval+ls i:=i+1 } WAttrib("texmode=off") end end #### broken code from here on, please fix it! #### for example, the actions() method parameters need to be same as above # # avatar - Penguin Version # # This shows the versatility of the abstract class: avatar. # As long as the specification of the avatar class is observed, # you can create any kind or form of avatars. This one is a penguin version. # # Note that the (origx, origy, origz) is located at the intersection # of the neck and body. # class penguin : avatar ( origx,origy,origz, # current X,Y,Z coordinate ro, # rotate matrix over whole avatar mv, # traslates matrix " " angle, # angle by which rotation should occur # Instances of following classes h, # penguinhead cam_angle ) # # move_part(Name, Dir, Angle) # Purpose: to move a particular body part either vertically or horizontally # Parameters: Name - name of the part to be moved # Dir - direction in which it is to move # Angle - angle for which it is to be rotated # method move_part(name, dir, angle) if name == "right_arm" then ra.setAngle(angle, dir) else if name == "left_arm" then la.setAngle(angle, dir) else if name == "right_leg" then rg.setAngle(angle, dir) else if name == "left_leg" then lg.setAngle(angle, dir) end # # move(X,Y,Z,Angle) # Purpose: to move the avatar # Parameters: [X,Y,Z] - current x, y, z coordinates # Angle - angle in which the avatar should be # turned # method move(posx,posy,posz,angle) degree := angle * (180/&pi) # convert angle(radian) to degree ro.angle := degree # update the angle of rotation matrix (e.g. ro) mv.x := posx # update the X coor. of translate matrix mv.y := posy # " Y " " mv.z := posz # " Z " " end # # setup() # Purpose: to set up each part of avatar by instantiating # the body part # method setup(x,y,z) # Setting up: cam_angle := 0 origx := x origy := y origz := z # Current coord. h := penguinhead() # head and neck end # # render() # Purpose: to render graphics of each part thus a whole # avatar # method render() PushMatrix() mv:=Translate(origx,origy,origz) # move the avatar ro:=Rotate(0,0,1,0) # and turn it h.render(face,color,hdchoice) # head and neck PopMatrix() end # # parser(File) # Purpose: Takes a file and parse each line and set them to their # appropriate variables # method parser(file) # dummy end method actions(type) case type of { # # move FORWARD # 1: { origz:=origz+cos(cam_angle)*0.1 origx:=origx+sin(cam_angle)*0.1 move(origx, origy, origz, cam_angle) #Refresh() } # # move BACKWARD - moon-walk style # 2: { origz:=origz-cos(cam_angle)*0.1 origx:=origx-sin(cam_angle)*0.1 move(origx, origy, origz, cam_angle) #Refresh() } # # move SIDEWAY-right # 3: { origx:=origx-sin(1.571-cam_angle)*0.1 origz:=origz+cos(1.571-cam_angle)*0.1 move(origx, origy, origz, cam_angle) #Refresh() } # # move SIDEWAY-left # 4: { origx:=origx+sin(1.571-cam_angle)*0.1 origz:=origz-cos(1.571-cam_angle)*0.1 move(origx, origy, origz, cam_angle) #Refresh() } # # turn LEFT # 5: { cam_angle:=cam_angle+0.05 if abs(cam_angle) > 2 * &pi then cam_angle := 0.0 move(origx, origy,origz, cam_angle) } # # turn RIGHT # 6: { cam_angle:=cam_angle-0.05 if abs(cam_angle) > 2 * &pi then cam_angle := 0.0 move(origx, origy,origz, cam_angle) } } end initially() X := 0 Y := 0 Z := 0 origx := 0 origy := 0 origz := 0 end # # Class: penguinhead # This class just renders penguinhead and neck # class penguinhead () method render() #Eyes DrawSphere(-0.07,1,-0.27,0.2) DrawSphere(-0.07,1,0.27,0.2) Fg("black") DrawSphere(-0.09,1,-0.27,0.182) #Eyeball DrawSphere(-0.09,1,0.27,0.182) #Beak PushMatrix() Translate(-0.6,0.75,0) Rotate(180,1,0,0) Rotate(270,0,0,1) Scale(1,1,1.4) Fg("yellow") DrawCylinder(0,0,0,0.8,0,0.3) PopMatrix() #Body PushMatrix() Rotate(270, 1, 0, 0) Scale(1,1,1.4) Fg("white") DrawSphere(0,0,0,0.55) Translate(0.4,0,0.2) Fg("black") DrawSphere(0,0,0,0.8) PopMatrix() #Wings PushMatrix() Translate(0.3,0.5,0.7) Rotate(90,1,0,0) Rotate(270,0,0,1) Rotate(325,0,1,0) Scale(1,2.5,4) Fg("black") DrawSphere(0,0,0,0.15) PopMatrix() PushMatrix() Translate(0.3,0.5,-0.7) Rotate(90,1,0,0) Rotate(270,0,0,1) Rotate(45,0,1,0) Scale(1,2.5,4) Fg("black") DrawSphere(0,0,0,0.15) PopMatrix() PushMatrix() Translate(0,-0.7,0) Scale(3,1,3) Fg("yellow") DrawSphere(0,0,-0.15,0.12) DrawSphere(0,0,0.15,0.12) PopMatrix() end end