Jump to content

caanmasu

Members
  • Content Count

    37
  • Joined

  • Last visited

  • Days Won

    2

caanmasu last won the day on May 19

caanmasu had the most liked content!

2 Followers

About caanmasu

  • Rank
    Novato

Recent Profile Visitors

475 profile views
  1. Hola amigos Esta quest consiste en que el líder del grupo al pulsar sobre un objeto (type 18) mostrará/ocultará la ubicación de los miembros del grupo (sin incluirlo a él) en el mapa. Parecido a cuando tenemos misión con un NPC y aparece una flecha arriba y también como una burbuja en el mapa. A medida que los miembros del grupo se mueven, también se moverá el "target", o sea, la "burbuja". Es decir, la ubicación es en tiempo real. No traigo vídeo porque no lo puedo testear en mi server pero sí funciona. Igualmente si no llegase a funcionar me lo escriben por acá. [Hidden Content] (Dejo código en post, código en web y archivo adjunto) --[[ QUEST Quest creada por Camilo Martínez Consiste en que el líder del grupo pueda ver la ubicación en tiempo real de los integrantes. Especificaciones: 1. El líder del grupo al darle click sobre el objeto, le aparecerá la ubicación de cada integrante en el mapa (en tiempo real) 2. Se notificará en el chat grupal cuando se active/desactive el rastreador 3. Cuando se le dé click de nuevo al objeto, se borrarán las ubicaciones. Notas: 1. Si un miembro no está en el mapa simplemente no se muestra su ubicación. 2. Al apuntar el cursor en cualquiera de los integrantes mostrados en el mapa, se verá su nombre. 3. Los targets se eliminan cuando se cierra la sesión 4. Basado en los targets de las misiones oficiales 5. Reportar cualquier error Y disfrutar de la quest! Discord: Camilo#0869 --]] quest ver_miembros begin state start begin function eliminar_targets() pc.setqf("block_target", 0) for i = 1, 8 do target.delete("__MEMBER"..i.."__") end end when 40001.use begin if party.is_leader() then if pc.getqf("block_target") == 0 then pc.setqf("block_target", 1) local pids = {party.get_member_pids()} local partyMembers = table.getn(pids) for i = 1, partyMembers do q.begin_other_pc_block(pids[i]) if pids[i] != pc.get_vid() then local name, pid = pc.get_name(), pids[i] end q.end_other_pc_block() target.vid("__MEMBER"..i.."__", pid, name) end party.chat("<Grupo> El líder está siguiendo las ubicaciones de los integrantes") else party.chat("<Grupo> El líder dejó de seguir las ubicaciones de los integrantes") ver_miembros.eliminar_targets() end else ver_miembros.eliminar_targets() syschat("No eres el líder de un grupo") end end when logout with pc.getqf("block_target") == 1 begin pc.setqf("block_target", 0) end end end ver_miembros.quest
  2. Corregí un pequeño error. Ya compila xD! Actualicen y arranquen!
  3. Hola mi gente! Hoy les traigo una quest elaborada 100% por mí desde la concepción de la idea xD Dale Me encorazona Vídeo demostrativo: go_all_map from Camilo Martinez on Vimeo. Descripción en el archivo de la quest Dale Me encorazona si te gustó EDITADO: Y agreguen la quest, las funciones en el questlib y por último agregar las funciones xx_coords_town_folder_map y list_folder_maps en el quest_functions (Revisa si tu objeto es type 18) Quest go_all_map.quest --[[ QUEST METIN2 Quest creada por Camilo Martínez Es un anillo teleport donde se puede acceder a la totalidad de los mapas del juego. Especificaciones: 1. Al darle clic al objeto, aparecerán botones de nombres página #, donde cada página muestra 43 mapas y la última los restantes mapas. 2. Al seleccionar una de las páginas y luego uno de los mapas, transportará al personaje a ese mapa en las coordenadas centrales Notas: 1. Recomendable para solo uso GM, esto es administrativo. Pero igual pueden usarlo a su antojo, solo es una recomendación :) 2. La cantidad máxima de botones por defecto puse 44 porque se bugeaba a los 45+ 3. No olvidar cambiar el país (locale/xx) por el de tu servidor 4. Se enlistan todas las líneas del index de la carpeta map. No debe haber ninguna línea vacía en ese archivo. Se toma el index y el nombre del mapa (nombre de la carpeta) por aparte. Luego con el nombre del mapa se va a la ruta del mapa y en Town.txt tomará la primera coordenada. Posteriormente se hace un warp_local donde se le envía el id del mapa y las coordenadas del Town*100 5. Si los separadores son espacio y tabulador, se tomará sin problema los datos de los archivos. Si hay varios espacios simulando un tabulador, no se tomará en cuenta. Es decir: Si tienes en Town.txt las coordenadas 433 542, habrá un error porque tienes dos espacios. Lo correcto es que haya un solo espacio o un solo tabulador. 6. Si no te transporta es porque el mapa puede estar mal implementado 7. No olvides poner la parte del questlib.lua 8. Tampoco olvides poner las funciones en quest_functions xx_coords_town_folder_map list_folder_maps 7. Cualquier error reportar 8. Que lo disfruten :) y como siempre, mi Discord: Camilo#0869 --]] quest go_all_map begin state start begin function info() return{ ["max_button"] = 44, ["country"] = "hungary", } end when 40004.use with pc.is_gm() begin local s = go_all_map.info().max_button local t = go_all_map.info().country local nombres_mapas, index_mapas = list_folder_maps(t) local cant_pags = math.ceil(table.getn(nombres_mapas)/(s-1)) local tabla_madre, tabla_select = {}, {} local tabla_madre_index = {}, {} local aux = 1 for i=1, cant_pags do table.insert(tabla_madre, {}) table.insert(tabla_madre_index, {}) table.insert(tabla_select, "Página "..i) for j=1, s-1 do tabla_madre[i][j] = nombres_mapas[aux] tabla_madre_index[i][j] = index_mapas[aux] aux = aux + 1 end table.insert(tabla_madre[i], "Cerrar") end table.insert(tabla_select, "Cerrar") local sel1 = select_table(tabla_select) if sel1 != table.getn(tabla_select) then local sel = select_table(tabla_madre[sel1]) if sel != table.getn(tabla_madre[sel1]) then local x, y = xx_coords_town_folder_map(t, tabla_madre[sel1][sel]) pc.warp_local(tabla_madre_index[sel1][sel], x*100, y*100) end end end end end Parte del questlib.lua function xx_coords_town_folder_map(country, map) local det, tab, spc = io.open('locale/'..country..'/map/'..map..'/Town.txt'), ' ', ' ' local x, y = 0, 0 for line in det:lines() do if table.getn(split(line, tab)) == 2 then x = split(line, tab)[1] y = split(line, tab)[2] return x, y elseif table.getn(split(line, spc)) == 2 then x = split(line, spc)[1] y = split(line, spc)[2] return x, y else return "ERROR" end end end function list_folder_maps(country) local map, index = {}, {} local det, tab, spc = io.open('locale/'..country..'/map/index'), ' ', ' ' for line in det:lines() do if table.getn(split(line, spc)) == 1 then table.insert(map, split(line,tab)[2]) table.insert(index, split(line, tab)[1]) else table.insert(map, split(line,spc)[2]) table.insert(index, split(line, spc)[1]) end end return map, index end go_all_map.rar
  4. El lenguaje Lua no tiene la propiedad de identación, o sea, que ignora si está tabulada o no, por lo que puedes usarla así pero tendrías que arreglarle partes donde hay palabras pegadas como "endend" Te recomiendo siempre identar todo el código para que puedas editarlo cómodamente si prefieres. Toma, te regalo mi quest. Esta quest es configurable, es decir, puedes agregar las perlas que quieras con su respectivo valor en trozos de piedra. Puedes agregar perlas doradas, moradas, plateadas, etc. tan solo agregándolas en las listas. Como siempre, haré una descripción de cómo funciona: si el jugador tiene el mínimo de trozos de piedra para comprar la perla de menos valor, le mostrará las perlas que puede cambiar y les aparecerá el nombre con la cantidad de trozos a cambiar. En este caso: Si tienes 100 trozos te aparecerá: Perla Blanca (50 trozos) Perla Azul (100 trozos) Si tienes 200 trozos te aparecerá: Perla Blanca (50 trozos) Perla Azul (100 trozos) Perla Roja (200 trozos) Si tienes 88 trozos de piedra te aparecerá: Perla Blanca (50 trozos) Y ya, el resto solo elimina los trozos correspondientes y te da la perla correspondiente, una sola. (Nota: es posible que al copiar este código aparezcan signos de interrogación al final de alguna línea, solo quítalos) --Camilo Martínez --Discord: Camilo#0869 quest cambiar_trozos_piedra begin state start begin function info() return { ["item"] = 27990, ["perlas"] = {27992, 27993, 27994}, ["valor"] = {50, 100, 200}, } end when 9009.chat."Cambiar Trozos de Piedra" begin local s = cambiar_trozos_piedra.info() local tabla_menu, tabla_perlas, tabla_valor = {}, {}, {} local cantidad = pc.count_item(s.item) if cantidad < s.valor[1] then setskin(0) syschat("No tienes suficientes "..item_name(s.item)) return end for i = 1, table.getn(s.perlas) do local perlas_desc = table.getn(s.perlas)-i+1 if cantidad/s.valor[perlas_desc] >= 1 then for j = 1, perlas_desc do tabla_perlas[j] = s.perlas[j] tabla_valor[j] = s.valor[j] tabla_menu[j] = item_name(s.perlas[j]).." ("..s.valor[j].." trozos)" end break end end table.insert(tabla_menu, "Cerrar") say_title(mob_name(npc.get_race())) local sel = select_table(tabla_menu) if sel == table.getn(tabla_menu) then return end pc.remove_item(s.item, tabla_valor[sel]) pc.give_item2(tabla_perlas[sel]) syschat("Cambio realizado") end end end
  5. Hay que testearla en un sv ya con jugadores porque en verdad no sé si afecte al servidor
  6. Hola amigo jajaja es verdad lo de la transparencia, te explicaré cómo funciona para que no te sientas inseguro xD En sí es un simulador, funciona de esta manera: Al arrastrar el objeto al alquimista determina el id del objeto, según el id va a tomar el addon_type. Primero revisa si el objeto tiene addon_type igual a -1 (o sea, que tiene bonus de media y habilidad). Si es así, entonces sale el menú de cuál media quieres sacar, habilidad y cuántos cambios quieres poner. Luego hay una función donde saco media y habilidad. Ver: Hará tantos ciclos hasta que llegue al número de cambios que pusiste o se cumpla la condición de que la habilidad o media que sacó el simulador es mayor o igual que la media o habilidad que pusiste. Después de encontrar la media o habilidad, habrá una función donde genera 5 cambios aleatorios (ahora explico cómo funciona) y de esos 5 tomo los tres primeros en caso de que haya salido bonus regular (media > 0 y hab > 0). Si salió media = 0 y hab != 0 entonces tomo 4 de los cambios generados, y lo mismo para la hab = 0, y así se obtienen los 5 bonus. Luego para el caso de los otros objetos de addon_type != -1, Simplemente generará 5 bonus de la siguiente manera: Creé una función que se llama verificar() donde toma los applytype# de ese ítem (del item_proto) y se guardan en un arreglo. Luego esos serán los bonus "prohibidos" o bloqueados. Para que cuando se haga la selección de bonus, no tome esos. O sea, si es una Tritón, no tomará velocidad de ataque (igual esa no saldrá porque no está en item_attr para armas), fuerza contra humanos ni fuerza contra demonios. Luego de tomar todos los bonus menos los prohibidos, el siguiente paso es tomar todos los bonus disponibles para ese ítem. Y ahí necesito sacar el type y sub_type. Si el type es 1, entonces es un arma y no importa el sub_type porque todas las armas tienen los mismos bonus disponibles. Si el type es 2 entonces no es un arma y hay que clasificarlo entre collar, brazalete, armadura, etc. con el sub_type. Sabiendo ya el subtype podemos sacar los bonus disponibles junto con los niveles de los bonus. Y la función retornará los bonus disponibles sin los prohibidos, para el objeto puesto encima del NPC. Luego creé una función llamada agregar_bonus donde saco 5 types aleatorios diferentes y 5 niveles diferentes de esos types. La variable aleatoria es uniforme porque no agregué la parte de la prob del item_attr, eso está en revisión. Esa función retorna 5 tipos de bonus cada uno con su nivel (aleatorio uniforme entre 1 y 5 cada uno de los bonus) Luego sí viene la parte interesante que es cuando se comparan. Se hace un ciclo hasta la cantidad de cambios o hasta que los bonus retornados de agregar_bonus sean iguales o mayores a cada uno de los bonus elegidos por el jugador. Obviamente validé de que no sean en orden aunque eso implica 5 veces menos rendimiento. Y cuando pase lo segundo, se agregará el bonus al objeto con item.set_value En resumen Validaciones: 1. Bonus prohibidos o bloqueados. Los bonus que ya vienen en el proto en applytype no saldrán como bonus disponibles o en otras palabras, los bonus que vienen fijos en el objeto no saldrán. 2. Bonus válidos. Se seleccionan los bonus del item_attr del sub_type del objeto y excluye los prohibidos. 3. Bonus sin repetir. El bonus elegido aleatoriamente no vuelve a salir. 4. Select con bonus válidos. Aparecerá en el seleccionador los bonus que tienen la posibilidad de salir en el objeto junto con los posibles valores que pueden salir. Optimizaciones: Para mejorar el rendimiento del simulador hice lo siguiente para la comparación de los 5 bonus generados con los elegidos: 1. En el primer type generado, si el primer type del bonus generado es igual a algún type del bonus elegido, entonces se hará la siguiente condición: Si el valor del bonus generado es mayor o igual al bonus elegido, entonces guardar y continuar con el siguiente type bonus. En el segundo type generado, si sucede lo mismo que en la primera pero para el segundo bonus generado, entonces guardará y continuará con el tercer type. Y así hasta el 5. Qué ocurre si no sucede lo mismo? pues continuará con el siguiente cambio o iteración. Algo más práctico: 1 -En este caso el primer bonus elegido por ti, salió en los bonus generados y el valor >= al que elegiste. 2 -Acá salió otro bonus válido 3 -Acá salió otro bonus válido. Ya van 3 en la misma iteración o cambio. 1 -Acá perdió la racha. O sea, el cuarto bonus tuyo no apareció dentro de la lista de los bonus generados. Y se cambiaron los bonus otra vez y apareció uno que sí coincide 1 -El siguiente bonus tampoco estaba, así que volvió a generar nuevos bonus y apareció uno que sí hace parte de los tuyos. 0 -El siguiente bonus no estuvo, así que se generaron nuevos bonus y... tu primer bonus no estuvo en la lista de bonus generados 0 -Aquí sucedió lo mismo. 1 -Y así xD 2 1 -Aquí empieza a tomar el primer bonus tuyo y lo compara con los generados. El primer bonus estuvo, bien. 2 -El segundo bonus también estuvo 3 -El tercer bonus también estuvo 4 -El cuarto bonus también estuvo 5 -El quinto bonus también estuvo. Aquí se terminan las iteraciones. De esta forma evito hacer iteraciones innecesarias. Aunque hace 5 ciclos en cada comparación, eso está en revisión. Y bueno, en la generación de bonus de media y habilidad no hay problema, está óptimo.
  7. Hola a todos Quiero mostrarles algo pero tampoco quiero ilusionarlos; no voy a compartir lo que he hecho, solo lo voy a mostrar y que den su opinión. Lo llamé Instant Bonus. La necesidad surge de lo demorado que es dopar un objeto. Más o menos sacar una media de 50 puede durar días completos, inventarios llenos de cambios e ir llenando a medida que se van acabando, y arrastrando uno a uno los cambios. Incluso para hacer los 5 bonus perfectos dura bastante, dependiendo de los niveles del bonus (5 niveles, por ejemplo en STR, 2, 4, 6, 8, 12); si los bonus tienen 5 niveles y quieres tenerlos todos al máximo solo te digo que es probablemente imposible. Aunque en los servidores privados esos niveles los "reducen" (por ejemplo en STR: 8, 10, 12) y será más fácil tener los bonus al máximo. Bien pues, luego de la idea del Switchbot, aunque redujo muchísimo el tiempo, todavía sigue quedado. Más o menos el Switchbot al máximo de velocidad hace como 3 cambios por segundo (si la estadística no me falla). Pues serían en un minuto 180 cambios, más o menos un pack por minuto. En una hora 10800 cambios, son 54 packs de 200 bonus y en el inventario (4 inventarios clásicos) caben 5x8 = 40, 40x4 = 160, 160 - 3 (3 es el tamaño del ítem), daría más o menos que en 3 horas se acaban los 4 inventarios llenos de cambios para un solo objeto en el Switchbot. Es decir que aproximadamente en 3 horas, en un solo objeto, se gasta 32400 cambios. En mi idea, ya puesta en práctica y funcional (ya lo verán en el vídeo), hará 1 millón de cambios en 1 a 5 segundos. Lean bien, un millón de cambios en un segundo. Mi InstantBonus en sacar los bonus en un arma con media y habilidad es de 100 mil a 300 mil veces más rápido que el Switchbot. ¿Impresionante, no? Es diferente para los objetos normales (sin media y habilidad) porque usan métodos diferentes. Esos sí hacen 10 mil cambios en unos 5 segundos. Aún así es muy bueno aunque no tanto como los de media. Lo que verán en el vídeo no es fake. Es algo ya creado, es real. Aún le falta agregarle el ítem.set_value y restringir la cantidad en los input pero eso no será tarea difícil. También me falta agregarle la probabilidad (player.item_attr columna prob) que aún no sé cómo se usa. Si alguno sabe cómo se usa esa prob me deja un mensajito por favor InstantBonus from Camilo Martinez on Vimeo.
  8. Edité la quest. Leer el editado en la publicación y actualizar! go go go
  9. Hola a todos! Hoy traigo otra quest, es un Evento Tanaka con la diferencia de que los GMs pueden ver los Tanakas en tiempo real en el mapa. Todos los GMs los pueden ver, no solo el GM que los invocó. Para más detalles leer el comentario del archivo de la quest. Si les gustó no olviden darle Like, piensen que están en Facebook :v (ba dum tss!) Un posible error que puede pasar es que cuando le den clic al pergamino no abra la misión. Yo cargo de nuevo todas las quest y hago reboot; luego sí compilo la actual. Cuando encuentre la razón de por qué no funciona el botón les cuento. No les quito más tiempo, link: [Hidden Content] Vidio random para todos: [Hidden Content] Quest Evento Tanakas Version 2 from Camilo Martinez on Vimeo. evento_tanakas_v2.quest --[[ QUEST Quest hecha por Camilo Martínez Consiste en el típico evento de Piratas Tanaka con la diferencia de que los GMs pueden ver la ubicación en el mapa grande de los piratas en tiempo real. Especificaciones: 1. Solo a los GMs les aparecerá un pergamino de misión. 2. Al darle clic, (estando en el mapa configurado en la quest) mencionará el nombre del monstruo a invocar y el rango mín-máx que se puede invocar. 3. Aparecerá un input() para digitar la cantidad de monstruos a invocar 4. Al invocarlos, aparecerá un anuncio a todos indicando el nombre del mob, cantidad de invocados y el mapa en donde te encuentras 5. Se asignarán targets o puntos en el mapa por cada pirata que invoques. 6. Se pueden invocar las oleadas que desees sin ningún problema 7. Al matar piratas botará una oreja con probabilidad modificable en la quest 8. Las orejas se cambiarán con el NPC 20095. Notas: 1. Todos los GMs pueden ver los monstruos en el mapa. Si no eres el GM que invocó, debes cambiar pj para verlos en el mapa. 2. Cada monstruo invocado se le asignará un vid (identificador) pero al morir, no se vuelve 0 el vid. Así que tuve que inventarme un reiniciador del contador de oleadas. El contador se reinicia en el NPC 20095 solo siendo GM. El contador es para mostrar a los GMs los puntos donde están los monstruos. Si los reinicias simplemente no se verán, así que recomendado que se reinicie cuando estés seguro de que no hayan piratas en el mapa. 3. El evento no tiene inicio y finalización, solo se invocan monstruos. 4. Reportar cualquier error Que la disfruten! Discord: Camilo#0869 --]] quest evento_tanakas_v2 begin state start begin function info() return { ["index_mapa"] = 63, ["nombre_mapa"] = "Desierto", ["id_mob"] = 5004, ["drop_mob"] = 30202, ["prob_mob"] = 50, -- del 1% al 100% (entero) ["radio_x"] = 1000, ["radio_y"] = 1000, ["max_invoc"] = 300, ["premios"] = { ["id"] = {10, 21, 32, 43, 54, 65, 76, 87, 98, 99}, ["cantidad"] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, ["precio"] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20} }, } end when letter with pc.is_gm() begin send_letter("GM: Evento Tanakas") for j = 1, game.get_event_flag("OleadaPirata") do for i = 1, evento_tanakas_v2.info().max_invoc do local vid = game.get_event_flag(j.."PIRATA"..i) target.vid(j.."PIRATA"..i, vid, mob_name(evento_tanakas_v2.info().id_mob)) end end end when button or info begin local s = evento_tanakas_v2.info() if pc.get_map_index() == s.index_mapa then say_title("Evento Tanakas") say("[ENTER]Hola "..pc.get_name()) say("[ENTER]Los "..mob_name(s.id_mob).." se invocarán en") say("el mapa actual.") say("[ENTER]Digita la cantidad a invocar (1-"..s.max_invoc..")") say("Deja vacío para cancelar") local cantidad = tonumber(input()) if cantidad == nil or cantidad == 0 or cantidad > s.max_invoc then return end game.set_event_flag("OleadaPirata", game.get_event_flag("OleadaPirata")+1) for i = 1, cantidad do local vid = mob.spawn(s.id_mob, pc.get_local_x(), pc.get_local_y(), s.radio_x, s.radio_y, 1) target.vid(game.get_event_flag("OleadaPirata").."PIRATA"..i, vid, mob_name(s.id_mob)) game.set_event_flag(game.get_event_flag("OleadaPirata").."PIRATA"..i, vid) end notice_all("Se han invocado "..cantidad.." "..mob_name(s.id_mob).." en "..s.nombre_mapa..". ¡Saca sus orejas!") else syschat("Debes estar en el desierto para poder invocar") end end when kill with npc.get_race() == evento_tanakas_v2.info().id_mob begin if number(1, 100) <= evento_tanakas_v2.info().prob_mob then game.drop_item_with_ownership(evento_tanakas_v2.info().drop_mob, 1) end end when 20095.chat."Reiniciar contador Evento Tanakas" with pc.is_gm() begin say_title(mob_name(npc.get_race())) say("[ENTER]El servidor hace una cantidad de ciclos cuando") say("invoca los tanakas. Si la cantidad de ciclos es muy grande,") say("puede ralentizar el proceso.") say("Actualmente el contador está en "..game.get_event_flag("OleadaPirata")) say("Solo reinicialo cuando no haya ningún Tanaka por ahí ") say("[ENTER]Reiniciarlo ahora?") if select("Sí ", "No") == 1 then game.set_event_flag("OleadaPirata", 0) syschat("Reiniciado") end end when 20095.chat."Cambiar orejas de Tanaka" begin -- Cambiar NPC si se necesita local s = evento_tanakas_v2.info() say_title("Cambiar orejas de Tanaka") local tabla_select = {} for i = 1, table.getn(s.premios.id) do tabla_select[i] = item_name(s.premios.id[i]).." x"..s.premios.cantidad[i].." - "..s.premios.precio[i] end table.insert(tabla_select, "Cerrar") local sel = select_table(tabla_select) if sel != table.getn(tabla_select) then if pc.count_item(s.drop_mob) >= s.premios.precio[sel] then pc.give_item2(s.premios.id[sel], s.premios.cantidad[sel]) pc.remove_item(s.drop_mob, s.premios.precio[sel]) else syschat("No tienes suficientes "..item_name(s.drop_mob)) end end end end end
  10. Brother borra la carpeta object, haz un make.sh, reboot, compila la quest y prueba; yo también tengo ese problema
  11. Hola a todos Traigo esta quest. Creada e ideada por mí, 100% original de Camilo. EDICIÓN URGENTE: añadí límite en los cambios/iteraciones. Eso depende del rendimiento de sus servidores. El personaje cuando tarda un minuto, estando en diálogo con un NPC haciendo un proceso, el servidor se cae. En la nueva edición, puse como máximo 2 millones; en mi server local se demora 6 segundos en llegar a los 2 millones. Pueden cambiar ese parámetro en la variable LIMITE. Descarga los archivos en el adjunto y mira todo de aquí para abajo. simulador.quest --[[ QUEST Quest creada por Camilo Martínez Esta quest fue creada con el fin de entretenimiento usando un simulador de media y habilidad. Especificaciones: 1. Dar clic al NPC indicado y abrirá una ventana con dos opciones: Sacar media y habilidad; Iteraciones infinitas 2. Al presionar sobre Iteraciones infinitas mostrará páginas de 10 filas donde se muestran números de media y habilidad aleatorios. Las páginas son infinitas en cuanto le presiones al botón "Siguiente". 3. Al presionar sobre Sacar media y habilidad, te pedirá la media deseada, la habilidad deseada y la cantidad de cambios (iteraciones) a usar. Si no quieres sacar habilidad, simplemente déjala en un número que sabes que no saldrá, como el 999. En iteraciones, elige un número muy grande. El resultado de esta operación es mostrar la cantidad de cambios utilizados para obtener la media o habilidad igual o mayor a las digitadas por ti. Notas: [ACADÉMICO] 1. La función para obtener estos valores está basada en la source del game en el archivo Item_addon.cpp 2. La media depende de la habilidad. Eso se puede ver en la función. La habilidad se saca de una distribución gaussiana (normal) con parámetros media (promedio) = 0 y desviación estándar = 5. Una vez obtenida la habilidad, se le suma 0.5 y si el valor obtenido es menor o igual a 20, sacará una función para la media. Si es mayor a 21, sacará otra función para sacar la media. 3. ¿Cómo obtener la función? ya que se trata de uso de números aleatorios para realizar simulaciones o eventos, la cosa cambia, hay que usar un método llamado Box-Muller. La función está en el questlib.lua y en simulador.py. La función number() o math.random() funcionan perfecto con el método ya que retornan variables aleatorias uniformes (todos los números caen con una probabilidad aproximadamente igual). 4. En C++ ya se encontraba la función gaussiana. En Python se encuenta como random.gauss() En Lua no se encontraba. Así que la tomé de Box-Muller. Al probar, me pareció que sacaba los valores muy cercanos a las de los otros dos lenguajes así que supongo que esta función simula muy bien. En ninguno de los tres lenguajes (aunque no se trata del lenguaje sino de la función), se logró obtener una media de 60. 5. La función de Box-Muller la encontré standard (media 0 y desviación estándar 1) así que tuve que averiguar una más genérica. Encontré una pero los resultados no me daban. La media no tenía problema porque sumaba con la función y la media es 0, así que daba igual. La desviación estándar estaba dentro de la raíz. Como no me daban bien los resultados (no pasaba de 40 de media(arma)), la elevé al cuadrado (quedó la desviación estándar afuera de la raíz) Los resultados cambiaron y se aproximaron bastante a mi simulación por Python. 6. La ventaja de usar el simulador es que puedes "usar" miles de Objeto Encantado en un segundo. Así que puedes poner libremente media de 50 y 1kk de cambios para probar. 7. Reportar cualquier error Que se entretengan :) Discord: Camilo#0869 --]] quest simulador begin state start begin function llenar_pagina() say_title("Habilidad Media") for j=1, 10 do local h, m = calcular_hab_med() say(h.." "..m) end end function sacar_bonus() LIMITE = 2000000 say("Ingresa la media que quieres sacar") local med = tonumber(input()) say("Ingresa la habilidad que quieres sacar") local hab = tonumber(input()) if med == nil or hab == nil then return end say("Ingresa la cantidad de cambios") say("(Máximo "..LIMITE..")") local iter = tonumber(input()) if iter == nill or iter > LIMITE then return end for i = 1, iter do local h, m = calcular_hab_med() if m >= med or h >= hab then say_title("Media y habilidad") say("[ENTER]Resultados: [ENTER]"..i.." cambios") say(m.." daño de media") say(h.." daño de habilidad") return end end syschat("No salió el bonus deseado") end when 20095.chat."Media y habilidad" begin local sel = select("Sacar media y habilidad", "Cambios infinitas", "Cerrar") if sel == 1 then simulador.sacar_bonus() elseif sel == 2 then simulador.llenar_pagina() while true do if select("Siguiente", "Cerrar") == 1 then simulador.llenar_pagina() else return end end end end end end questlib.lua function gaussian (mean, variance) return variance*math.sqrt(-2 * math.log(math.random())) * math.cos(2 * math.pi * math.random()) + mean end function calcular_hab_med() local g = gaussian(0, 5) local hab = math.floor(g) + 0.5 local med = 0 if math.abs(hab) <= 20 then med = -2*hab+math.abs(number(-8, 8) + number(-8, 8))+number(1, 4) else med = -2*hab+number(1, 5) end return math.floor(hab), math.floor(med) end Este código es para simular por Python3 por local o web. Deshabilita el print de adentro para que no aparezca en cada iteración la media y la habilidad. Este archivo no va en ninguna parte del juego, aclaro. #Simulador de media y habilidad. La probabilidad de sacar media y habilidad es la clásica del oficial import random import math def calcularmedia(num, intentos): for i in range(intentos): valor_bonus = 500 n1 = random.gauss(0, 5) iSkillBonus = int(n1) + float(0.5) iNormalHitBonus = 0 if math.fabs(iSkillBonus) <= 20: iNormalHitBonus = -2 * iSkillBonus + math.fabs(random.randint(-8, 8) + random.randint(-8, 8)) + random.randint(1, 4) else: iNormalHitBonus = -2 * iSkillBonus + random.randint(1, 5) hab = "Habilidad", int(iSkillBonus) med = "Media", int(iNormalHitBonus) print (med, hab) if iNormalHitBonus >= num: return (i+1), "cambios", med, hab, "Yang gastado", (i+1)*valor_bonus return "no dopó, Yang gastado: ", (i+1)*valor_bonus #En donde va el 50 es la media y el 1000000 es la cantidad de cambios a utilizar print (calcularmedia(30, 1000000)) Éxitos!
  12. Hola NazoX Muchas gracias por tu comentario. Tienes toda la razón. Lo he corregido. Leer descripción y actualizar quest!
  13. Hola! He traído una nueva quest, creada por mí. Link: [Hidden Content] Toda la descripción está en el archivo. Adáptenla a sus servers EDIT: 1. He agregado la confirmación del personaje a transportar --[[ QUEST Quest creada por Camilo Martínez Consiste en que el líder del grupo transporta a un miembro hacia él. Al pulsar sobre el ítem (type 18) abrirá una ventana donde se visualizan los nombres de los integrantes del grupo y al seleccionar a uno, le llegará al integrante un cuadro donde tiene que confirmar la teletransportación. En caso de afirmativo, llegará a la posición del líder. Notas: 1. Solo aparecerán los miembros del grupo que estén en el mismo mapa que el líder 2. El tiempo de espera se puede modificar 3. Los botones del select se bugean con los corchetes del nombre del GM. Así que haz pruebas con un pj que no tenga esos caracteres. 4. El objeto cuando está en estado de confirmación se bloquea. Es decir, solo se puede hacer una invitación a la vez. 5. Solo files 40k+ 6. Reportar cualquier error Buena suerte :) Discord: Camilo#0869 --]] quest anillo_teleport_lider begin state start begin when 40003.use with party.is_leader() begin TIEMPO_ESPERA = 10 local pids = {party.get_member_pids()} local partyMembers = table.getn(pids) local lider = party.get_leader_pid() local members, members_pids = {}, {} local index_map = pc.get_map_index() for i = 1, partyMembers do q.begin_other_pc_block(pids[i]) if pids[i] != lider then if pc.get_map_index() == index_map then table.insert(members, pc.get_name()) table.insert(members_pids, pids[i]) end end q.end_other_pc_block() end table.insert(members, "Cerrar") local sel = select_table(members) if sel != table.getn(members) then setskin(NOWINDOW) syschat("Se le ha enviado una invitación a "..members[sel]) local res = confirm(members_pids[sel], pc.get_name().." quiere transportarte. ¿Aceptas?", TIEMPO_ESPERA) if res == CONFIRM_OK then local x = pc.get_local_x()*100 local y = pc.get_local_y()*100 local r = pc.select(members_pids[sel]) pc.warp_local(index_map, x, y) pc.select(r) elseif res == CONFIRM_TIMEOUT then syschat("Se acabó el tiempo de espera") else syschat(members[sel].." ha rechazado la invitación de transportación") end end end end end
  14. Editado: Actualicen quest!
×
×
  • Create New...