Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- very very very very basic!! gps script by Basshunter
- nah, a lenyeg:
- kell egy graf, amit ra tudunk vetiteni a jatek terkepere es a pontjai kb az utak fobb
- pontjainal, keresztezodeseknel vannak.
- grafot ugy hatarozzuk meg, h megadjuk a pontjait es h melyik pontbol melyik ponto(ka)t
- lehet elerni, azaz, h mik a graf elei.
- ahhoz, h a gps script jol menjen minden pontbol kell letesiteni utat minden pontba,
- ha a graf nem lenne osszefuggo, akk letezne ket olyan pont,ami kozott nem letesitheto ut,
- az meg szopas lenne.
- letezik egy Dijkstra nevu matematikusrol elnevezett algoritmus, ami arra jo, h
- megkeresi a grafban ket pont kozott a legkisebb koltseggel jaro utat.
- ez egy naggyon fasza dolog, utana lehet olvasni pl itt
- https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
- errol meg reszletesebben az algoritmus kodjanal van iras
- a script lenyege kb annyi, h a jatekos a mapon kivalaszt egy waypoint-ot
- (jobb click a map-on) es a gps automatikusan megjeleniti neki az utvonalat.
- a gps lekorlatozodik egy varosreszre, a jatekos poziciojat nezve megkeresi a
- hozza legkozelebb levo pontot es onnan navigalja el a waypoint-hoz legkozelebb eso
- pontig. tehat ha faszsag van neki megadva, ami kivul esik a varosreszen, a
- script mukodese nem lessz kiszamithato es jelentkezhetnek erdekessegek :D
- szoval keretik a waypointot lehetoseg szerint kozel rakni az egyik node-hoz...:)
- node-ok keszitesse:
- /node-val letrehozod az elsot, akk megjelenik a 3d cucc es annak segitsegevel latod
- az id-jet, igy a /neighbour ID ID ID ID max 6 id-ig letrehoz olyan node-t ami a megadott
- node-ok szomszedja igy fogja tudni az algoritmus, h melyikbol melyikbe mehet.
- a vegen MENTSD EL, /savenodes :D
- egyebb:
- /closestnode odateleportal a hozzad legkozelebb eso node-hoz
- ENJOY
- nagyjabol ennyi :D
- */
- /*
- alap nodes.txt (LS nyugati(?) resze /closestnode...):
- 1037.941772,-1572.491333,13.066694,2,4,19,-1,-1,-1 NODE #1
- 918.464416,-1572.841186,13.062478,1,3,11,-1,-1,-1 NODE #2
- 915.921569,-1489.605102,13.055746,2,4,6,8,-1,-1 NODE #3
- 1048.655395,-1494.401367,13.066202,1,3,5,-1,-1,-1 NODE #4
- 1060.554809,-1400.661376,13.148726,4,6,12,18,-1,-1 NODE #5
- 917.615112,-1400.747802,12.944102,3,5,7,14,-1,-1 NODE #6
- 796.244567,-1401.111694,13.093589,6,8,15,17,-1,-1 NODE #7
- 793.483398,-1480.477294,13.066370,3,7,9,-1,-1,-1 NODE #8
- 771.503112,-1586.994018,13.062499,8,10,23,-1,-1,-1 NODE #9
- 838.253173,-1613.024658,13.062537,9,11,-1,-1,-1,-1 NODE #10
- 874.620117,-1577.971069,13.065388,2,10,-1,-1,-1,-1 NODE #11
- 1058.217285,-1324.285644,13.062490,5,13,22,-1,-1,-1 NODE #12
- 942.958312,-1323.725463,13.066369,12,14,-1,-1,-1,-1 NODE #13
- 917.088256,-1323.538818,13.191036,13,6,15,-1,-1,-1 NODE #14
- 797.102722,-1322.802856,13.062549,14,7,16,-1,-1,-1 NODE #15
- 632.878356,-1319.955200,13.157868,15,17,-1,-1,-1,-1 NODE #16
- 632.589172,-1400.801269,13.012390,7,16,23,-1,-1,-1 NODE #17
- 1198.745239,-1401.550781,12.965830,5,19,20,-1,-1,-1 NODE #18
- 1196.037719,-1571.765380,13.087066,1,18,-1,-1,-1,-1 NODE #19
- 1209.086914,-1281.450927,13.086853,18,21,-1,-1,-1,-1 NODE #20
- 1149.150512,-1280.644775,13.321684,20,22,-1,-1,-1,-1 NODE #21
- 1058.386230,-1281.693359,13.454155,21,12,-1,-1,-1,-1 NODE #22
- 632.233093,-1586.422485,15.230491,17,9,-1,-1,-1,-1 NODE #23
- */
- #include <a_samp>
- #include <streamer> // streamer plugint igenyel azt elvileg lehet hasznalni
- #define MAX_NODES 100
- #define MAX_NEIGHBOURS 6
- #define INVALID_NEIGHBOUR -1
- #define INVALID_NODE 0
- #define INITIAL_NODE 1
- #define RACE_CP_SIZE 12
- #define yellow 0xffff00ff
- #define red 0xff0000ff
- enum NodeStruct {
- Float:X,
- Float:Y,
- Float:Z,
- Neighbours[MAX_NEIGHBOURS]
- };
- new NodeCount = INITIAL_NODE;
- new Float:Nodes[MAX_NODES][NodeStruct];
- new ShortestPath[MAX_PLAYERS][MAX_NODES];
- new PlayerPathNode[MAX_PLAYERS];
- public OnFilterScriptInit()
- {
- new File:nodes = fopen("nodes.txt", io_read);
- if (!nodes) {
- printf("A nodes.txt fajl nem talalhato!");
- return 0;
- }
- new buffer[128];
- while (fread(nodes, buffer)) {
- sscanf(buffer, "fffiiiiii", Nodes[NodeCount][X], Nodes[NodeCount][Y], Nodes[NodeCount][Z], Nodes[NodeCount][Neighbours][0], Nodes[NodeCount][Neighbours][1], Nodes[NodeCount][Neighbours][2], Nodes[NodeCount][Neighbours][3], Nodes[NodeCount][Neighbours][4], Nodes[NodeCount][Neighbours][5]);
- new formatstring[128];
- format(formatstring, 128, "Node #{FF0000}%i", NodeCount);
- CreateDynamic3DTextLabel(formatstring, yellow, Nodes[NodeCount][X], Nodes[NodeCount][Y], Nodes[NodeCount][Z], 150);
- //CreateDynamicMapIcon(Nodes[NodeCount][X], Nodes[NodeCount][Y], Nodes[NodeCount][Z], 0, yellow);
- NodeCount++;
- }
- fclose(nodes);
- return 1;
- }
- public OnPlayerClickMap(playerid, Float:fX, Float:fY, Float:fZ)
- {
- new Float:x, Float:y, Float:z;
- if (IsPlayerInAnyVehicle(playerid)) GetVehiclePos(GetPlayerVehicleID(playerid), x, y, z);
- else GetPlayerPos(playerid, x, y, z);
- new c_player = GetClosestNodeFromPoint(x,y,z);
- printf("Jatekoshoz kozel eso node: %i", c_player);
- new c_waypoint = GetClosestNodeFromPoint(fX,fY,fZ);
- printf("Waypoint-hoz kozel eso node: %i", c_waypoint);
- printf("Dijkstra: %i-tol %i-ig...", c_player, c_waypoint);
- new PathNodeCount = Dijkstra(c_player, c_waypoint, ShortestPath[playerid]);
- if (PathNodeCount == 0) return 1;
- PlayerPathNode[playerid] = PathNodeCount-1;
- new CurrentNode = ShortestPath[playerid][PlayerPathNode[playerid]];
- if (PathNodeCount == 1) SetPlayerRaceCheckpoint(playerid, 1, Nodes[CurrentNode][X], Nodes[CurrentNode][Y], Nodes[CurrentNode][Z], 0, 0, 0, RACE_CP_SIZE);
- else {
- new NextNode = ShortestPath[playerid][--PlayerPathNode[playerid]];
- SetPlayerRaceCheckpoint(playerid, 0, Nodes[CurrentNode][X], Nodes[CurrentNode][Y], Nodes[CurrentNode][Z], Nodes[NextNode][X], Nodes[NextNode][Y], Nodes[NextNode][Z], RACE_CP_SIZE);
- }
- SendClientMessage(playerid, yellow, "Navigacio elinditva, kovesd a checkpointokat!");
- return 1;
- }
- public OnPlayerEnterRaceCheckpoint(playerid)
- {
- if (PlayerPathNode[playerid] == -1) {
- DisablePlayerRaceCheckpoint(playerid);
- SendClientMessage(playerid, yellow, "Megerkeztel!");
- return 1;
- }
- new CurrentNode = ShortestPath[playerid][PlayerPathNode[playerid]];
- if (PlayerPathNode[playerid] == 0) {
- SetPlayerRaceCheckpoint(playerid, 1, Nodes[CurrentNode][X], Nodes[CurrentNode][Y], Nodes[CurrentNode][Z], 0, 0, 0, RACE_CP_SIZE);
- PlayerPathNode[playerid]--;
- } else {
- new NextNode = ShortestPath[playerid][--PlayerPathNode[playerid]];
- SetPlayerRaceCheckpoint(playerid, 0, Nodes[CurrentNode][X], Nodes[CurrentNode][Y], Nodes[CurrentNode][Z], Nodes[NextNode][X], Nodes[NextNode][Y], Nodes[NextNode][Z], RACE_CP_SIZE);
- }
- return 1;
- }
- public OnPlayerCommandText(playerid, cmdtext[])
- {
- if (strcmp("/closestnode", cmdtext, true) == 0)
- {
- new Float:x, Float:y, Float:z;
- if (IsPlayerInAnyVehicle(playerid)) GetVehiclePos(GetPlayerVehicleID(playerid), x, y, z);
- else GetPlayerPos(playerid, x, y, z);
- new id = GetClosestNodeFromPoint(x,y,z);
- if (IsPlayerInAnyVehicle(playerid)) SetVehiclePos(GetPlayerVehicleID(playerid), Nodes[id][X], Nodes[id][Y], Nodes[id][Z]);
- else SetPlayerPos(playerid, Nodes[id][X], Nodes[id][Y], Nodes[id][Z]);
- return 1;
- }
- if (strcmp("/savenodes", cmdtext, true, 10) == 0)
- {
- new File:nodes = fopen("nodes.txt", io_append);
- new formatstring[128];
- for (new i = INITIAL_NODE; i < NodeCount; i++) {
- format(formatstring, 128, "%f,%f,%f,%i,%i,%i,%i,%i,%i NODE #%i\n", Nodes[i][X], Nodes[i][Y], Nodes[i][Z], Nodes[i][Neighbours][0], Nodes[i][Neighbours][1], Nodes[i][Neighbours][2], Nodes[i][Neighbours][3], Nodes[i][Neighbours][4], Nodes[i][Neighbours][5], i);
- fwrite(nodes, formatstring);
- }
- fclose(nodes);
- SendClientMessage(playerid, yellow, "Node-ok mentve a nodes.txt-be!");
- return 1;
- }
- if (strcmp("/node", cmdtext, true, 10) == 0){
- new Float:x, Float:y, Float:z;
- if (IsPlayerInAnyVehicle(playerid)) GetVehiclePos(GetPlayerVehicleID(playerid), x, y, z);
- else GetPlayerPos(playerid, x, y, z);
- Nodes[NodeCount][X] = x;
- Nodes[NodeCount][Y] = y;
- Nodes[NodeCount][Z] = z;
- for (new i = 0; i < MAX_NEIGHBOURS; i++) Nodes[NodeCount][Neighbours][i] = INVALID_NEIGHBOUR;
- new formatstring[128];
- format(formatstring, 128, "Node #{FF0000}%i", NodeCount);
- CreateDynamic3DTextLabel(formatstring, yellow, x, y, z, 150);
- CreateDynamicMapIcon(x, y, z, 0, yellow);
- format(formatstring, 128, "Node #%i elkeszitve", NodeCount);
- SendClientMessage(playerid, yellow, formatstring);
- NodeCount++;
- return 1;
- }
- if (strcmp("/neighbour", cmdtext, true, 10) == 0){
- new Float:x, Float:y, Float:z;
- if (IsPlayerInAnyVehicle(playerid)) {
- GetVehiclePos(GetPlayerVehicleID(playerid), x, y, z);
- } else {
- GetPlayerPos(playerid, x, y, z);
- }
- Nodes[NodeCount][X] = x;
- Nodes[NodeCount][Y] = y;
- Nodes[NodeCount][Z] = z;
- for (new i = 0; i < MAX_NEIGHBOURS; i++) Nodes[NodeCount][Neighbours][i] = INVALID_NEIGHBOUR;
- new formatstring[128];
- format(formatstring, 128, "Node #{FF0000}%i", NodeCount);
- CreateDynamic3DTextLabel(formatstring, yellow, x, y, z, 150);
- CreateDynamicMapIcon(x, y, z, 0, yellow);
- // baszakodas addig, amig vannak parameterei a parancsnak
- new neighbours[32];
- new params = 0;
- new index = strlen("/neighbour");
- new tmp[32], tmplen = 0;
- while (cmdtext[index] || tmplen) {
- new ch = cmdtext[index];
- if (ch == ' ' || ch == '\0') {
- if (tmplen) {
- params++;
- if (params > MAX_NEIGHBOURS) {
- SendClientMessage(playerid, red, "Szomszedok felso hatara: 6");
- return 1;
- }
- new nodeid = strval(tmp);
- format(neighbours, 32, "%s #%i", neighbours, nodeid);
- new bool:success = false;
- for (new i = 0; i < MAX_NEIGHBOURS; i++) {
- if (Nodes[nodeid][Neighbours][i] == INVALID_NEIGHBOUR) {
- Nodes[nodeid][Neighbours][i] = NodeCount;
- success = true;
- break;
- }
- }
- if (!success) {
- format(formatstring, 128, "A #%i node elerte a szomszedok maximalis szamat!", nodeid);
- SendClientMessage(playerid, red, formatstring);
- return 1;
- } else {
- for (new i = 0; i < MAX_NEIGHBOURS; i++) {
- if (Nodes[NodeCount][Neighbours][i] == INVALID_NEIGHBOUR) {
- Nodes[NodeCount][Neighbours][i] = nodeid;
- success = true;
- break;
- }
- }
- }
- /*format(formatstring, 128, "param: %s", tmp);
- SendClientMessage(playerid, yellow, formatstring);*/
- for (new i = 0; tmp[i]; i++) tmp[i] = '\0';
- tmplen = 0;
- if (ch == '\0') break;
- }
- }
- else tmp[tmplen++] = ch;
- index++;
- }
- format(formatstring, 128, "Node #%i letrehozva, szomszedai: %s", NodeCount, neighbours);
- SendClientMessage(playerid, yellow, formatstring);
- NodeCount++;
- return 1;
- }
- return 0;
- }
- // ket pont tavolsagat szamitja ki a Pitagorasz tetel segitsegevel
- stock Float:Dist(Float:x1,Float:y1,Float:z1,Float:x2,Float:y2,Float:z2) {
- return floatsqroot(floatpower((x2-x1),2)+floatpower((y2-y1),2)+floatpower((z2-z1),2));
- }
- // megvaltoztatja egy mapicon szinet
- stock ChangeDynamicMapIconColor(id, color) {
- return Streamer_SetIntData(STREAMER_TYPE_MAP_ICON, id, E_STREAMER_COLOR, color);
- }
- // megadja a ponthoz legkozelebbi node-ot
- stock GetClosestNodeFromPoint(Float:x, Float:y, Float:z) {
- new nodeid = INVALID_NODE, Float:mindist = Float:FLOAT_INFINITY;
- for (new i = 1; i < NodeCount; i++) {
- new Float:dist = Dist(x,y,z, Nodes[i][X], Nodes[i][Y], Nodes[i][Z]);
- if (dist < mindist) {
- mindist = dist;
- nodeid = i;
- }
- }
- return nodeid;
- }
- // Dijkstra algoritmus implementacioja
- // a source a kiindulo node, a target pedig a cel node, ezek kozott kell a legjobb ut
- // a kod a wikipedian talalhato Pseudocode alapjan lett implementalva
- stock Dijkstra(source, target, result[]) {
- new Float:dist[MAX_NODES], prev[MAX_NODES], bool:visited[MAX_NODES], visited_nodes = 0;
- for (new v = INITIAL_NODE; v < NodeCount; v++) { // Initialization
- dist[v] = FLOAT_INFINITY; // Unknown distance from source to v
- prev[v] = INVALID_NODE; // Previous node in optimal path from source
- visited[v] = false; // All nodes initially in Q (unvisited nodes)
- }
- dist[source] = 0; // Distance from source to source
- while (visited_nodes < (NodeCount-1)) {
- new u = INVALID_NODE, Float:mindist = FLOAT_INFINITY;
- for (new v = INITIAL_NODE; v < NodeCount; v++) {
- if (!visited[v] && dist[v] < mindist) { // ez elso alkalommal nyilvanvaloan a kiindulo node-t fogja eredmenyezni, hisz az 0
- mindist = dist[v];
- u = v;
- }
- }
- // megjegyezzuk, h ez a node mar meg volt latogatva, igy ne terjunk vissza feleslegessen hozza
- visited[u] = true;
- visited_nodes++;
- // ha a node a celallomas, akk meg is van a legjobb utvonal
- if (u == target) {
- new index = 0;
- printf("A Dijkstra utvonalat talalt:");
- while (prev[u] != INVALID_NODE) {
- result[index] = u;
- index++;
- printf("%i", u);
- u = prev[u];
- }
- result[index] = u;
- printf("%i", u);
- return index+1;
- }
- // meg kell nezni u osszes meg nem latogatott v szomszedjat
- for (new i = 0; i < MAX_NEIGHBOURS; i++) {
- new v = Nodes[u][Neighbours][i];
- if (v != INVALID_NEIGHBOUR && !visited[v]) { // where v is still in Q.
- new Float:alt = dist[u] + Dist(Nodes[u][X], Nodes[u][Y], Nodes[u][Z], Nodes[v][X], Nodes[v][Y], Nodes[v][Z]);
- if (alt < dist[v]) { // A shorter path to v has been found
- dist[v] = alt;
- prev[v] = u;
- }
- }
- }
- }
- return 0;
- }
- // http://wiki.sa-mp.com/wiki/Sscanf_code
- // kicsit minimalizalva lett, csak a szukseges dolgokkal
- stock sscanf(string[], format[], {Float,_}:...)
- {
- if (string[0] == 0 || (string[0] == 1 && string[1] == 0))return format[0];
- new formatPos = 0,stringPos = 0,paramPos = 2,paramCount = numargs(),delim = ',';
- while (string[stringPos] && string[stringPos] <= ' ')stringPos++;
- while (paramPos < paramCount && string[stringPos])
- {
- switch (format[formatPos++])
- {
- case '\0':return 0;
- case 'i', 'd': {
- new neg = 1,num = 0,ch = string[stringPos];
- if (ch == '-'){
- neg = -1;
- ch = string[++stringPos];
- }do{
- stringPos++;
- if ('0' <= ch <= '9')num = (num * 10) + (ch - '0');
- else return -1;
- }
- while ((ch = string[stringPos]) > ' ' && ch != delim);
- setarg(paramPos, 0, num * neg);
- }
- case 'f':{
- new changestr[16], changepos = 0, strpos = stringPos;
- while(changepos < 16 && string[strpos] && string[strpos] != delim)
- changestr[changepos++] = string[strpos++];
- changestr[changepos] = '\0';
- setarg(paramPos,0,_:floatstr(changestr));
- }
- case 'p': {
- delim = format[formatPos++];
- continue;
- }
- case '\'':{
- new end = formatPos - 1, ch;
- while ((ch = format[++end]) && ch != '\'') {}
- if (!ch)return -1;
- format[end] = '\0';
- if ((ch = strfind(string, format[formatPos], false, stringPos)) == -1){
- if (format[end + 1])return -1;
- return 0;
- }
- format[end] = '\'';
- stringPos = ch + (end - formatPos);
- formatPos = end + 1;
- }
- default:continue;
- }
- while (string[stringPos] && string[stringPos] != delim && string[stringPos] > ' ')stringPos++;
- while (string[stringPos] && (string[stringPos] == delim || string[stringPos] <= ' '))stringPos++;
- paramPos++;
- }do{
- if ((delim = format[formatPos++]) > ' '){
- if (delim == '\'')while ((delim = format[formatPos++]) && delim != '\'') {}
- else if (delim != 'z')return delim;
- }
- }
- while (delim > ' ');
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement