v1.0 Release
Features
- Controls are similar to Dizzasters map editor. (Because it is the most common editor.)
- Added relative positioning mode.
- Very simple and useful.
- (For v1.0 Beta most features are disabled so you might need wait for updates.)
Controls
- R - Resets object rotation.
- Delete - Deletes an object selected.
- Backspace - Stop controlling an object.
- Object can be selected by shooting it once.
Commands
- /editor - Enable or disable map editor.
- /savemap - Saves map.
- /objectlist - Listing all created objects. (With editor)
- /addobject - Listing all created objects.
- /selectobject - Selects object with id.
- /removeobject - Removes object with id.
- /cloneobject - Clones an object selected.
- Arrow keys - Movements and rotation.
SERVER SIDE
main.nut[noae][noae]
function onScriptLoad(){
dofile("scripts/editor.nut"); MonScriptLoad();
}
function onPlayerJoin(player){
MonPlayerJoin(player);
}
function onClientScriptData( player ) { local int=Stream.ReadInt(), str=Stream.ReadString();
if (int == 939381){onNewKeyUp(player,str)} else if (int == 939382){onNewKeyDown(player,str)}
}
function onNewKeyUp(player,key){MonKeyUp(player,key)}
function onNewKeyDown(player,key){MonKeyDown(player,key)}
function onPlayerCommand(player,cmd,text){
MonPlayerCommand(player,cmd,text);
}
function onObjectShot( object, player, weapon ){MonObjectShot( object, player, weapon )}
function find(str,string){if(string.find(str)!= null){return true;}else{return false;}}
function FindAndReplace(string,findString,Replace){
if (find(findString,string)&&findString!=string){ local n=-1;
do{n++
if(n+findString.len()<=string.len()){
if(string.slice(n,n+findString.len())==findString){ local prev=null,next=null;
if(n==0){prev="";}else{prev=string.slice(0,n)}
if(n+Replace.len()==string.len()){next=""}else{next=string.slice(n+findString.len(),string.len())}
string = format("%s%s%s"prev,Replace,next); n=string.len()+1;
return string;
}
}
}while (n<string.len())
}else{return string;}
}
function GetTok(string, separator, n, ...){
local m = vargv.len() > 0 ? vargv[0] : n,tokenized = split(string, separator),text = "";
if (n > tokenized.len() || n < 1) return null;
for (; n <= m; n++){text += text == "" ? tokenized[n-1] : separator + tokenized[n-1];}return text;
}
function NumTok( string, separator){local tokenized = split(string, separator); return tokenized.len();}
[/noae][/noae]
editor.nut[noae][noae]
class MapEditor{ editing=false; reposition=true; selectedobj=null; speed=0.1; motion=null; motioning=false; }
function MonScriptLoad(){
MapDB <- ConnectSQL( "MapDB.db" ); map <- array(GetMaxPlayers(), null); MapObjects <- "";
QuerySQL(MapDB, "create table if not exists Map (List NUMERIC DEFAULT 0,Model NUMERIC DEFAULT 0,World NUMERIC DEFAULT 0,X TEXT, Y TEXT,Z TEXT,rX TEXT, rY TEXT,rZ TEXT, Alpha TEXT)");
createMapObjects();
}
function MonPlayerJoin(player){ map[player.ID] = MapEditor(); }
function MonPlayerCommand(player,cmd,text){
if (cmd=="cmds"||cmd=="commands"){
MessagePlayer("[#3486eb](/) [#ffffff]editor, savemap, objectlist", player);
MessagePlayer("[#3486eb](/) [#ffffff]addobject, removeobject, selectobject, cloneobject", player);
}
else if (cmd=="editor"){
if (map[player.ID].editing == false){map[player.ID].editing = true; MessagePlayer("[#3486eb]# [#ffffff]Map editor mod enabled.", player);}
else {map[player.ID].editing = false; map[player.ID].selectedobj = null; MessagePlayer("[#3486eb]# [#ffffff]Map editor mod disabled.", player);}
}
else if (cmd=="savemap"){
if (map[player.ID].editing == false){return false;}
saveMapObjects()
}
else if (cmd=="objectlist"){ local list=""
for (local i = 0; i < GetObjectCount()+1; i++){
if (GetTok(MapObjects, ",", i)){
local object = FindObject(GetTok(MapObjects,",",i).tointeger());
if (object){if (list == ""){list = "[#34e5eb]ID: [#ffffff]"+object.ID}else{list = list+", [#34e5eb]ID: [#ffffff]"+object.ID}}
}
}text = "[#3486eb]|Object List| ";MessagePlayer("[#3486eb]# [#ffffff]"+text, player);MessagePlayer("[#3486eb]# [#ffffff]"+list, player);
}
else if (cmd=="addobject"){
if (map[player.ID].editing == false){return false;}
if (!text){MessagePlayer("[#3486eb]# [#ffffff]You must enter numeric value for object model.", player);}
if (IsNum(text)){
local model = text.tointeger(), world = player.World,pos = player.Pos,alpha = 255,ObjID = CreateObject( model, world, pos, alpha ).ID;
FindObject(ObjID).TrackingShots = true; addMapObject(ObjID); map[player.ID].selectedobj = FindObject(ObjID);
MessagePlayer("[#3486eb]# [#ffffff]Object with model number "+model+" created. ID: "+ObjID+"", player);
MessagePlayer("[#3486eb]# [#ffffff]Selected object with id:"+ObjID+"", player);
}
else{MessagePlayer("[#3486eb]# [#ffffff]You must enter numeric value for object model.", player);}
}
else if (cmd=="removeobject"){
if (map[player.ID].editing == false){return false;}
if (!text){MessagePlayer("[#3486eb]# [#ffffff]You must enter numeric value for object ID.", player);}
if (!IsNum(text)){MessagePlayer("[#3486eb]# [#ffffff]You must enter numeric value for object ID.", player); return false;}
if (FindObject(text.tointeger())){deleteMapObject(text.tointeger());}
MessagePlayer("[#3486eb]# [#ffffff]Object with id: "+text+" deleted", player);
}
else if (cmd=="selectobject"){
if (map[player.ID].editing == false){return false;}
if (!text){MessagePlayer("[#3486eb]# [#ffffff]You must enter numeric value for object ID.", player);}
if (!IsNum(text)){MessagePlayer("[#3486eb]# [#ffffff]You must enter numeric value for object ID.", player); return false;}
local obj = FindObject(text.tointeger());
local found = 989898;for (local i = 0; i < 100; i++){local plr = FindPlayer(i); if (plr){if (map[plr.ID].selectedobj == obj){found = i;}}}
if (found == true){MessagePlayer("[#3486eb]# [#ffffff]"+FindPlayer(found.tointeger).Name+" is using this object now. Select another one.", player); return false;}
if (obj){ map[player.ID].selectedobj = obj;
MessagePlayer("[#3486eb]# [#ffffff]Selected object with id:"+text+"", player);
}else{MessagePlayer("[#3486eb]# [#ffffff]ID: "+text+" not found. Try with another id.", player);}
}
else if (cmd=="cloneobject"){
if (map[player.ID].editing == false){return false;}
if (map[player.ID].selectedobj){local object = map[player.ID].selectedobj;
local model = object.Model, world = object.World,pos = object.Pos,alpha = 255,ObjID = CreateObject( model, world, pos, alpha ).ID;
FindObject(ObjID).TrackingShots = true; addMapObject(ObjID); map[player.ID].selectedobj = FindObject(ObjID);
map[player.ID].selectedobj = FindObject(ObjID);
MessagePlayer("[#3486eb]# [#ffffff]Cloned object " + text + " at its position", player);
MessagePlayer("[#3486eb]# [#ffffff]Selected object with id:"+ObjID+"", player);
}
}
else{
MessagePlayer("[#3486eb]# [#ffffff]''"+cmd+"'' command not found. Use /cmds or /commands to see all commands.", player)
}
}
function MonObjectShot( object, player, weapon ){
if (map[player.ID].editing == true){
local found = false;
for (local i = 0; i < 100; i++){local plr = FindPlayer(i); if (plr){if (map[plr.ID].selectedobj == object){found = true;}}}
if (found == true) return false;
MessagePlayer("[#3486eb]# [#ffffff]Selected object with id:"+object.ID+"", player)
map[player.ID].selectedobj = object;
}
}
function speedUP(player){
switch(map[player.ID].speed){
case 0.1: map[player.ID].speed = 0.6; MessagePlayer("[#3486eb]# [#ffffff]Movement speed is: NORMAL",player); break;
case 0.6: map[player.ID].speed = 1.1; MessagePlayer("[#3486eb]# [#ffffff]Movement speed is: FAST",player); break;
case 1.1: map[player.ID].speed = 1.6; MessagePlayer("[#3486eb]# [#ffffff]Movement speed is: VERY FAST",player); break;
case 1.6: MessagePlayer("[#3486eb]# [#ffffff]Movement speed is: VERY FAST",player); break;
}
}
function speedDOWN(player){
switch(map[player.ID].speed){
case 0.1: MessagePlayer("[#3486eb]# [#ffffff]Movement speed is: SLOW",player); break;
case 0.6: map[player.ID].speed = 0.1; MessagePlayer("[#3486eb]# [#ffffff]Movement speed is: SLOW",player); break;
case 1.1: map[player.ID].speed = 0.6; MessagePlayer("[#3486eb]# [#ffffff]Movement speed is: NORMAL",player); break;
case 1.6: map[player.ID].speed = 1.1; MessagePlayer("[#3486eb]# [#ffffff]Movement speed is: FAST",player); break;
}
}
function PUP(player,object){
if (map[player.ID].reposition == true){object.Pos.z += map[player.ID].speed;}
else{object.RotateByEuler( Vector( map[player.ID].speed, 0, 0 ), 100 );}
}
function PDOWN(player,object){
if (map[player.ID].reposition == true){object.Pos.z -= map[player.ID].speed;}
else{object.RotateByEuler( Vector( -map[player.ID].speed, 0, 0 ), 100 );}
}
function UP(player,object){
if (map[player.ID].reposition == true){
local rel = calculateAngle(player);
switch(rel){
case 1: object.Pos.x -= map[player.ID].speed; break;
case 2: object.Pos.y -= map[player.ID].speed; break;
case 3: object.Pos.y += map[player.ID].speed; break;
case 4: object.Pos.x += map[player.ID].speed; break;
case 5: object.Pos.y -= map[player.ID].speed; break;
case 6: object.Pos.y += map[player.ID].speed; break;
}
}else{object.RotateByEuler( Vector( 0, map[player.ID].speed, 0 ), 100 );}
}
function DOWN(player,object){
if (map[player.ID].reposition == true){
local rel = calculateAngle(player);
switch(rel){
case 1: object.Pos.x += map[player.ID].speed; break;
case 2: object.Pos.y += map[player.ID].speed; break;
case 3: object.Pos.y -= map[player.ID].speed; break;
case 4: object.Pos.x -= map[player.ID].speed; break;
case 5: object.Pos.y += map[player.ID].speed; break;
case 6: object.Pos.y -= map[player.ID].speed; break;
}
}else{object.RotateByEuler( Vector( 0, -map[player.ID].speed, 0 ), 100 );}
}
function RIGHT(player,object){
if (map[player.ID].reposition == true){
local rel = calculateAngle(player);
switch(rel){
case 1: object.Pos.y -= map[player.ID].speed; break;
case 2: object.Pos.x += map[player.ID].speed; break;
case 3: object.Pos.x -= map[player.ID].speed; break;
case 4: object.Pos.y += map[player.ID].speed; break;
case 5: object.Pos.x += map[player.ID].speed; break;
case 6: object.Pos.x -= map[player.ID].speed; break;
}
}else{object.RotateByEuler( Vector( 0, 0, map[player.ID].speed ), 100 );}
}
function LEFT(player,object){
if (map[player.ID].reposition == true){
local rel = calculateAngle(player);
switch(rel){
case 1: object.Pos.y += map[player.ID].speed; break;
case 2: object.Pos.x -= map[player.ID].speed; break;
case 3: object.Pos.x += map[player.ID].speed; break;
case 4: object.Pos.y -= map[player.ID].speed; break;
case 5: object.Pos.x -= map[player.ID].speed; break;
case 6: object.Pos.x += map[player.ID].speed; break;
}
}else{object.RotateByEuler( Vector( 0, 0, -map[player.ID].speed ), 100 );}
}
function calculateAngle(player){
local a = player.Angle;
if (a > 0){if (0.8 < a && a < 2.4){return 1;}else{if (a > 2.4){return 2;}else if (a < 0.8){return 3;}}}
else{if (-2.4 < a && a < -0.8){return 4;}else{if (-2.4 > a){return 5;}else if (-0.8 < a){return 6;}}}
}
function MonKeyUp(player,key){
if (map[player.ID].motion != null){ map[player.ID].motion.Delete(); map[player.ID].motion = null;}
}
function MonKeyDown(player,key){
if ( typeof player != "instance" ){player = FindPlayer(player); if (!player){return false}}
if (map[player.ID].editing == true && map[player.ID].selectedobj != null){
local obj = FindObject(map[player.ID].selectedobj.ID);
switch (key)
{
case "Up": UP(player,obj); break;
case "Down": DOWN(player,obj); break;
case "Right": LEFT(player,obj); break;
case "Left": RIGHT(player,obj); break;
case "PUp": PUP(player,obj); break;
case "PDown": PDOWN(player,obj); break;
case "R":
obj.RotateToEuler( Vector( 0, 0, 0 ), 0 );
MessagePlayer( "[#3486eb]# [#ffffff]Rotation angles have been reset", player );
break;
case "One":
switch(map[player.ID].speed){
case 0.1:
map[player.ID].speed = 0.6;
MessagePlayer("[#3486eb]# [#ffffff]Movement speed is: NORMAL",player);
break;
case 0.6:
map[player.ID].speed = 1.1;
MessagePlayer("[#3486eb]# [#ffffff]Movement speed is: FAST",player);
break;
case 1.1:
map[player.ID].speed = 1.6;
MessagePlayer("[#3486eb]# [#ffffff]Movement speed is: VERY FAST",player);
break;
case 1.6:
map[player.ID].speed = 0.1;
MessagePlayer("[#3486eb]# [#ffffff]Movement speed is: SLOW",player);
break;
}
break;
case "Two":
if (map[player.ID].reposition == true){map[player.ID].reposition=false;
MessagePlayer("[#3486eb]# [#ffffff]Positioning mode closed. Rotating mode opened.", player);
}else{map[player.ID].reposition=true;
MessagePlayer("[#3486eb]# [#ffffff]Positioning mode opened. Rotating mode closed.", player);
}
break;
case "Delete":
deleteMapObject(obj.ID);
MessagePlayer("[#3486eb]# [#ffffff]Object has been removed",player);
map[player.ID].selectedobj = null;
break;
case "BackSpace":
map[player.ID].selectedobj = null;
MessagePlayer("[#3486eb]# [#ffffff]You have finished editing the object",player);
break;
}
if (key == "Up" || key == "Down" || key == "Right" || key == "Left" || key == "PUp" || key == "PDown"){
if (map[player.ID].motion == null){map[player.ID].motion = NewTimer("MonKeyDown", 100, 0, player.ID,key);}
}
}
}
function createMapObjects(){
for (local i = 0; i < 5000; i++){
local q = QuerySQL(MapDB, "SELECT * FROM Map WHERE List = '" + i + "'");
if (q){
local list = GetSQLColumnData(q, 0).tointeger(),
model = GetSQLColumnData(q, 1).tointeger(),
world = GetSQLColumnData(q, 2).tointeger(),
X = GetSQLColumnData(q, 3).tofloat(),
Y = GetSQLColumnData(q, 4).tofloat(),
Z = GetSQLColumnData(q, 5).tofloat(),
rX = GetSQLColumnData(q, 6).tofloat(),
rY = GetSQLColumnData(q, 7).tofloat(),
rZ = GetSQLColumnData(q, 8).tofloat(),
alpha = GetSQLColumnData(q, 9).tointeger(),
pos = Vector(X,Y,Z);
CreateObject( model, world, pos, alpha );
local ObjID = GetObjectCount()-1;
FindObject(ObjID).TrackingShots = true;
FindObject(ObjID).RotateToEuler(Vector(rX,rY,rZ),0);
addMapObject(ObjID)
}
}
}
function addMapObject(ObjID){
if (MapObjects == ""){MapObjects = ObjID.tostring();}
else{MapObjects = MapObjects+","+ObjID;}
}
function deleteMapObject(ObjID){
ObjID = ObjID.tointeger()
local object = FindObject(ObjID);
if (object){
if (find(","+ObjID,MapObjects)){MapObjects = FindAndReplace(MapObjects,","+ObjID,"");}
else if (find(ObjID+",",MapObjects)){MapObjects = FindAndReplace(MapObjects,ObjID+",","");}
else{MapObjects = "";}
object.Delete()
}
}
function saveMapObjects(){
QuerySQL(MapDB,"DELETE FROM Map"); local a = 0;
for (local i = 0; i < GetObjectCount()+1; i++){
if (GetTok(MapObjects, ",", i)){
local object = FindObject(GetTok(MapObjects,",",i).tointeger());
if (object){
QuerySQL(MapDB, "INSERT INTO Map (List, Model, World , X, Y, Z, rX ,rY,rZ, Alpha) VALUES ( '"
+ a + "','"
+ object.Model + "','"
+ object.World + "','"
+ object.Pos.x + "','"
+ object.Pos.y + "','"
+ object.Pos.z + "','"
+ object.RotationEuler.x + "','"
+ object.RotationEuler.y + "','"
+ object.RotationEuler.z + "','"
+ object.Alpha + "' )");
a++;
}
}
}
if (a == 0){Message("[#3486eb]# [#ffffff]Database has been reset.");}
else{Message("[#3486eb]# [#ffffff]"+a+" object saved to database.");}
}
[/noae][/noae]
CLIENT SIDE
main.nut[noae][noae]
local Enter = KeyBind( 0x0D );
local BackSpace = KeyBind( 0x08 );
local Shift = KeyBind( 0x10 );
local Delete = KeyBind(0x2E);
local Up = KeyBind(0x26);
local Down = KeyBind(0x28);
local Left = KeyBind(0x25);
local Right = KeyBind(0x27);
local PUp = KeyBind(0x21);
local PDown = KeyBind(0x22);
local One = KeyBind(0x31);
local Two = KeyBind(0x32);
local I = KeyBind(0x49);
local L = KeyBind(0x4C);
local R = KeyBind(0x52);
function KeyBind::OnUp(key){
switch(key){
case Enter: SendDataToServer("Enter", 939381); break;
case BackSpace: SendDataToServer("BackSpace", 939381); break;
case Shift: SendDataToServer("Shift", 939381); break;
case Delete: SendDataToServer("Delete", 939381); break;
case Up: SendDataToServer("Up", 939381); break;
case Down: SendDataToServer("Down", 939381); break;
case Left: SendDataToServer("Left", 939381); break;
case Right: SendDataToServer("Right", 939381); break;
case PUp: SendDataToServer("PUp", 939381); break;
case PDown: SendDataToServer("PDown", 939381); break;
case One: SendDataToServer("One", 939381); break;
case Two: SendDataToServer("Two", 939381); break;
case I: SendDataToServer("I", 939381); break;
case L: SendDataToServer("L", 939381); break;
case R: SendDataToServer("R", 939381); break;
}
}
function KeyBind::OnDown(key){
switch(key){
case Enter: SendDataToServer("Enter", 939382); break;
case BackSpace: SendDataToServer("BackSpace", 939382); break;
case Shift: SendDataToServer("Shift", 939382); break;
case Delete: SendDataToServer("Delete", 939382); break;
case Up: SendDataToServer("Up", 939382); break;
case Down: SendDataToServer("Down", 939382); break;
case Left: SendDataToServer("Left", 939382); break;
case Right: SendDataToServer("Right", 939382); break;
case PUp: SendDataToServer("PUp", 939382); break;
case PDown: SendDataToServer("PDown", 939382); break;
case One: SendDataToServer("One", 939382); break;
case Two: SendDataToServer("Two", 939382); break;
case I: SendDataToServer("I", 939382); break;
case L: SendDataToServer("L", 939382); break;
case R: SendDataToServer("R", 939382); break;
}
}
function SendDataToServer(s, i){local msg=Stream();msg.WriteInt(i.tointeger());msg.WriteString(s);Server.SendData(msg);}
[/noae][/noae]
Update Notes:
- Code has been reproduced
- Added more features
- Added client side key event to server side key event
- Bug fixes
Thanks to you, community is growing.
nice work.
Code has been reproduced.