create_actor

Started by habi, Apr 28, 2020, 08:04 PM

Previous topic - Next topic

habi

yeah. finally..

What is it?
creating random actors here and there in server.
here and there?
yes. at any place u want.
how many?
atmost some 40 without lag. i created a seventy five one of them with lag
75 what?
bots/actors.

Tell me the cmd to create it.
it goes like create_actor x y z

Enough. To experienced scripters, i explain what this is. A python program will run  with your server -it is a socket server. you connect a socket to it
socket.Send("create_actor 116 lance -661.12 756.365 11.0966 0")and actor is ready within seconds.

If you have knowledge about packets,
How many packets are send?
one packet per bot in every 2 seconds. it is a ping packet. otherwise it disconnects. Packets are send to the server from python program.

hi guys, i did not know python. for this purpose i learned it.

actor is a word used in vice city script file to the player, cop, pedestrians etc. you might know.
How much time the actor lives?
Until you "destroy_actor id"

So what are the commands you developed?
create_actor skinID name x y z angle
set_actor_pos id x y z
set_actor_health id 100
for the first actor you create, id will be 1, then 2, then 3, and so on.

Any other? Two more commands are there, which i developed by evening.
set_actor_weapon id 22
set_actor_angle id 3.14


codes here
Also, i recommend you to use cmdinputrel by ysc, to have easy interaction with bots.

Sebastian

This is pretty insane :D nice!

NicusorN5

Unique work dude! You're a legend!

habi

Quote from: Athanatos on Apr 29, 2020, 06:35 PMUnique work dude! You're a legend!
thanks.  and now actor walk, etc is making.

umar4911

Finally, I can record some insane video clips without searching for online clan members.

Great Work!
RT Member | Asian City Scripter | CTB Contributor | VKs Contributor | European City Contributor | EAD Scripter

PANZER24

Quote from: habi on Apr 29, 2020, 07:07 PM
Quote from: Athanatos on Apr 29, 2020, 06:35 PMUnique work dude! You're a legend!
thanks.  and now actor walk, etc is making.
Hey, I'm overwhelmingly impressed by your work and thought, instead of making commands for movement that when using them it will take an eternity to create something, how about you use the same technique as in this video?
https://www.youtube.com/watch?v=drvzFYCX7Gk


letting players record their movement and apply it on an actor?

habi

#6
Quote from: PANZER24 on Apr 30, 2020, 01:40 AMHey, I'm overwhelmingly impressed by your work and thought, instead of making commands for movement that when using them it will take an eternity to create something, how about you use the same technique as in this video?
letting players record their movement and apply it on an actor?
thanks.
I think it can be done.
sniffing packet and sending it. Iet's see

MEGAMIND

habi the steps u wrote above are correct but sometimes its better to creat a small video on how it done, so in upcoming future its easier for everyone on how to do it, well othern then that u are a gift to this community made such an interesting thing no one could possibly think off instead of making dummy hard models u made a real live like actor, great work man!

habi

Quote from: MEGAMIND on Apr 30, 2020, 12:18 PMhabi the steps u wrote above are correct but sometimes its better to creat a small video on how it done, so in upcoming future its easier for everyone on how to do it, well othern then that u are a gift to this community made such an interesting thing no one could possibly think off instead of making dummy hard models u made a real live like actor, great work man!
thanks. I will make a video so everyone understands it better

DMWarrior

#9
Good job on this one, habi!

Far from perfect, of course, but it's way better than previous workarounds (which required you to join and open multiple games) and it can be used for testing or just to play around the city. And because you keep sending packets to keep them on server, they also could be used on things like shops or other locations.

Inspired by your idea, I decided to make something similar using node.js instead of Python. Here's my attempt.

Code used for recording packets (name it "record.js"):
[noae][noae]///////////////////////////////////////////////////////////////////////////////
// @file modules.js
///////////////////////////////////////////////////////////////////////////////
/** Arguments passed though command line. */
var args = process.argv.slice(2);

/** Filesystem module. */
var fs = require("fs");

/** Datagram module (used for UDP conections). */
var dgram = require("dgram");

/** Properties and settings. */
var properties = {
// Server (proxy).
"server": {
"address"  : "localhost",
"port"     : 1234, // <- RECORDER PORT
"exclusive": true
},

// Server (VC:MP).
"vcmp": {
"address": "localhost",
"port"   : 7777 // <- VC:MP SERVER PORT
},

// Client (proxy).
"client": {
"address": null,
"port"   : null
},

// Packet options.
"packets": {
"sent"                : 0,
"received"            : 0,
"displaySentEvery"    : 25,
"displayReceivedEvery": 25,
"foundName"           : false,
"name"                : "Default",
"recordingEnabled"    : true,
},

// Saved data.
"data": {
"name"         : "",
"nameIndexAt"  : 0,
"nameAppearsAt": 0,
"packets"      : []
}
};

// Change player name:
properties.packets.name = args[0] || properties.packets.name;

///////////////////////////////////////////////////////////////////////////////
// @file server.js
///////////////////////////////////////////////////////////////////////////////
/** UDP server. */
var server = dgram.createSocket("udp4");

/**
 * Event called by server when an error has occurred.
 *
 * @param {Error} error Error.
 */
server.on("error", function (error) {
  console.log("[SERVER] Error: " + error.stack);
  server.close();
});

/**
 * Event called by server when it received a message.
 *
 * @param {Buffer} message Message received.
 * @param {Object} remote Conection information.
 */
server.on("message", function (message, remote) {
// Save client's conection information. This will be necessary in order to
// redirect data to VC:MP later:
properties.client = {
"address": remote.address,
"port"   : remote.port
};

// Finding what packet has the player name is useful, because we can change
// it later:
if(properties.packets.foundName === false) {
var messageString = message.toString();
var namePacket = messageString.indexOf(properties.packets.name);

// When player name is found, it's index and position are saved:
if(namePacket >= 0) {
properties.data.name = properties.packets.name;
properties.data.nameIndexAt = namePacket;
properties.data.nameAppearsAt = properties.data.packets.length;

// Notify that the player name has been found:
console.log("<< SERVER >> Found player name at packet " + properties.data.nameAppearsAt + ".");
properties.packets.foundName = true;
}
}

// Count packets received (and toggle a "display" variable):
properties.packets.received += 1;
var display = (properties.packets.received % properties.packets.displayReceivedEvery == 0);

// Record packets (if enabled):
if(properties.packets.recordingEnabled === true) {
properties.data.packets.push(message.toJSON().data);
}

// Redirect message to VC:MP Server:
client.send(message, properties.vcmp.port, properties.vcmp.address, function (error) {
if(error) {
console.log("<< CLIENT >> << ERROR >>");
}
});
});

/**
 * Event called by server when it's listening for conections.
 */
server.on("listening", function () {
  var remote = server.address();
  console.log("[SERVER] Listening on \"" + remote.address + ":" + remote.port + "\"");
});

///////////////////////////////////////////////////////////////////////////////
// @file client.js
///////////////////////////////////////////////////////////////////////////////
/** UDP client. */
var client = dgram.createSocket("udp4");

/**
 * Event called by client when it receives a message.
 *
 * @param {Buffer} message Message received.
 * @param {Object} remote Conection information.
 */
client.on("message", function (message, remote) {
// Count packets sent (and toggle a "display" variable):
properties.packets.sent += 1;
var display = (properties.packets.sent % properties.packets.displaySentEvery == 0);

// If this conection is from VC:MP, it'll be sent back to client:
server.send(message, properties.client.port, properties.client.address, function (error) {
if(error) {
console.log("<< SERVER >> << ERROR >>");
}
});
});

///////////////////////////////////////////////////////////////////////////////
// @file index.js
///////////////////////////////////////////////////////////////////////////////
// Listen server...
server.bind(properties.server);

/**
 * Event called when application is closed.
 */
process.on("SIGINT", function () {
// Save packets to a file (if enabled):
if(properties.packets.recordingEnabled) {
var file = fs.writeFileSync(properties.data.name + ".json", JSON.stringify(properties.data));
}

// Notify that the application is being closed:
console.log("Application closed (" + properties.packets.received + " packets received; " + properties.packets.sent + " packets sent).");
process.exit(0);
});
[/noae][/noae]

Code used for playing packets (name it "play.js"):
[noae][noae]///////////////////////////////////////////////////////////////////////////////
// @file modules.js
///////////////////////////////////////////////////////////////////////////////
/** Arguments passed though command line. */
var args = process.argv.slice(2);

/** Filesystem module. */
var fs = require("fs");

/** Datagram module (used for UDP conections). */
var dgram = require("dgram");

/** Properties and settings. */
var properties = {
  // Server (VC:MP).
"vcmp": {
"address": "localhost",
"port"   : 7777 // <- VC:MP SERVER PORT
},

// Packet options.
  "packets": {
"counter"      : 0,
    "sent"         : 0,
"total"        : 0,
"name"         : "Default",
"replacedName" : false,
"intervalSpeed": 50
  },

// Saved data.
  "data": JSON.parse(fs.readFileSync(args[0] + ".json", "utf8"))
};

// Salve total of packets available and change player name:
properties.packets.total = properties.data.packets.length;
properties.packets.name = args[1] || properties.data.name;

///////////////////////////////////////////////////////////////////////////////
// @file client.js
///////////////////////////////////////////////////////////////////////////////

/** UDP client. */
var client = dgram.createSocket("udp4");

/** Interval used to send packets to VC:MP Server. */
var interval = setInterval(function () {
// Loop through after reaching the last available packet:
if(properties.packets.counter > (properties.packets.total - 1)) {
properties.packets.counter = 0;
}

// Get next packet to be sent:
var message = properties.data.packets[properties.packets.counter];

// If this is the packet where player name appears, it will be replaced:
if(properties.packets.replacedName === false && properties.packets.counter == properties.data.nameAppearsAt) {
// Iterate though characters...
for(var i = 0; i <= properties.data.name.length; i++) {
var char = properties.packets.name.charCodeAt(i);

// If new name is shorter than the previous one, set null string
// terminator and finish:
if(isNaN(char) === true) {
message[properties.data.nameIndexAt + i] = 0;
break;
}

// Replace character...
message[properties.data.nameIndexAt + i] = char;
}

// This name only needs to be replaced once:
properties.packets.replacedName = true;
}

// Send packet to VC:MP Server:
client.send(Buffer.from(message), properties.vcmp.port, properties.vcmp.address, function (error) {
if(error) {
console.log("<< CLIENT >> << ERROR >>");
}
});

// Increment total packets sent and counter:
properties.packets.sent += 1;
  properties.packets.counter += 1;
}, properties.packets.intervalSpeed);
[/noae][/noae]

For recording, use: node record.js <playername>
For playing, use: node play.js <filename> <playername>

Make sure to change some values in the "properties" variable before using it.

I managed to record and then spawn bots driving cars around the city. Since I made it to loop, these bots will quit and then come back to server to do the same thing all over again.



It just makes things like scripting a server so much more enjoyable to test in my opinion, even if these bots don't do anything useful. There's a huge difference between test a server alone or with 2 or 3 players and with a server full of people running around and preventing the city from feeling empty.

We could do a lot more if we knew the structure of packets, though. This would help a lot, specially for things like hit detection (deal and take damage from bots) and movement.

It's kinda funny to see how NPCs exist in other multiplayers, like MTA:SA, but nobody uses them, yet VC:MP, which could benefit from it to compensate low player counts, is the only GTA multiplayer mod which doesn't have this feature yet. Hopefully we can at least find workarounds like these to see how it would be like to having them.

NicusorN5

I really feel bad for not trying to create a similar thing. But I should try making a custom plugin.

MEGAMIND

while running node record.js no packets get sent or recived aftermintaing the process just a .json file is created with{"name":"","nameIndexAt":0,"nameAppearsAt":0,"packets":[]}so? do u install any npm module or what?

habi

#12
Quote from: DMWarrior on May 01, 2020, 12:56 PMGood job on this one, habi!
Thank you

Quote from: DMWarrior on May 01, 2020, 12:56 PMIt just makes things like scripting a server so much more enjoyable to test in my opinion, even if these bots don't do anything useful. There's a huge difference between test a server alone or with 2 or 3 players and with a server full of people running around and preventing the city from feeling empty.
yeah sure. a server full of people. some walking. some shooting. some dancing. the Malibu club can be exactly recreated.

Quote from: DMWarrior on May 01, 2020, 12:56 PMWe could do a lot more if we knew the structure of packets, though. This would help a lot, specially for things like hit detection (deal and take damage from bots) and movement.
for a week, I was doing this. I can contribute to packet structure.
do you know how I decrypt packets? eg. I used to go to vector 0 0 0 in golf club, set gravity to 0, so player not falls. then study the packet

@Athanatos
Quote from: Athanatos on May 01, 2020, 01:06 PMI really feel bad for not trying to create a similar thing. But I should try making a custom plugin.
A custom plugin so that squirrel server can communicate directly i.e. without sockets if possible.

DMWarrior

#13
Quote from: MEGAMIND on May 01, 2020, 03:46 PMwhile running node record.js no packets get sent or recived aftermintaing the process just a .json file is created with{"name":"","nameIndexAt":0,"nameAppearsAt":0,"packets":[]}so? do u install any npm module or what?

Here's a quick guide.

Setting up properties

The way I'm using to capture packets is by using a proxy. Basically, it works like this:



Now we're going to record on a local server. On the image above, we're using the default port used by VC:MP Blank Server, which is 8192, and port 3000 for our proxy.

On "record.js", find and set these property values:
// Server (proxy).
 "server": {
 "address"  : "localhost",
 "port"     : 3000, // <- RECORDER PORT
 "exclusive": true
 },

 // Server (VC:MP).
 "vcmp": {
 "address": "localhost",
 "port"   : 8192 // <- VC:MP SERVER PORT
 }

On "play.js", find and set these property values:
// Server (VC:MP).
 "vcmp": {
 "address": "localhost",
 "port"   : 8192 // <- VC:MP SERVER PORT
 }

Everything should be now set up! Open your VC:MP server and run the recorder with node record.js <playername>.

The <playername> refers to the name you have set on VC:MP.



If my name is set as "Player" on VC:MP, then I need to start the recorder using node record.js Player.

Entering the server

When our local server is added on favourites, we usually click on it and play. But in order to record our packets, we need to join on the proxy instead. Since we did set port 3000 for it, we need to add this server on our favourites now.



Now you'll have 2 servers on your list.



They're all the same, except the one we just set on port 3000 is saving all our packets and redirecting everything back to the real server. This is the one we need to join.

Join the server on port 3000 and play normally. Everything you do should is now being recorded by our proxy. There's no warning in game telling you that, everything is silently happening on our node.js server.



When you're done, close the node.js server. The file should be now full of contents inside. Also, if you see a message like << SERVER >> Found player name at packet <number>., then your name did match and everything is right!

Because I'm using "Player", the file generated will be "Player.json".

Spawning our bot

Now use node play.js <filename> <playername>. The playername refers to the name you want the bot to be called.

If I want to call it "Robot", then I need to use node play.js Player Robot.

Now we can just join the server normally (the one on port 8192). If everything is right, we should now see a player called "Robot" doing the same movements we did when we were on proxy!



When you're done with it, close the node.js server. The bot will eventually "timeout" and leave.

Quote from: habi on May 01, 2020, 05:02 PMfor a week, I was doing this. I can contribute to packet structure.
do you know how I decrypt packets? eg. I used to go to vector 0 0 0 in golf club, set gravity to 0, so player not falls. then study the packet

Unfortunately, no. I don't really understand how this works.

MEGAMIND

awsome just tested out, unique and neat