Tokei

Members
  • Content Count

    452
  • Avg. Content Per Day

    0
  • Joined

  • Last visited

  • Days Won

    46

Tokei last won the day on August 5

Tokei had the most liked content!

Community Reputation

362 Excellent

About Tokei

  • Rank
    Metaling

Profile Information

  • Gender
    Male
  • Location
    Canada

Recent Profile Visitors

10,917 profile views
  1. Well, this adds a flat 80 hit to all players and enemies. While yes, it does help with your initial issue, it also makes flee builds a lot less worthwhile (it gives a free Phreeoni card to everyone). If that works out for you, then that's up to you...! Although it seems to me your biggest concern is the flee bonus that the higher level monsters get. Why not simply remove that instead? // Flee stat = status->flee; stat += level + status->agi + (bl->type == BL_MER ? 0 : bl->type == BL_PC ? status->luk / 5 : 0) + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100 status->flee = cap_value(stat, 1, SHRT_MAX); to // Flee stat = status->flee; stat += (bl->type == BL_MOB ? 0 : level) + status->agi + (bl->type == BL_MER ? 0 : bl->type == BL_PC ? status->luk / 5 : 0) + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100 status->flee = cap_value(stat, 1, SHRT_MAX);
  2. Heya, Well, the function that determines whether you hit or miss the target is is_attack_hitting in battle.cpp. This is purely based on the hit vs flee between you and the target though. Mobs with higher levels have more flee because of the formula they use (in status.cpp): // Flee stat = status->flee; stat += level + status->agi + (bl->type == BL_MER ? 0 : bl->type == BL_PC ? status->luk / 5 : 0) + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100 status->flee = cap_value(stat, 1, SHRT_MAX); What you're asking for doesn't really fit well with the current system though.
  3. Heya, This is possible, but it usually means the solution/algoritm you're trying to use is the wrong one to start with. That aside, you can use something similar to: duplicate "prontera", 154, 182, 4, "SourceNPC", "DuplicatedNPC", 77; And you'll have to do the changes below: diff --git a/src/map/npc.hpp b/src/map/npc.hpp index 0ce0c96a0..ffde62587 100644 --- a/src/map/npc.hpp +++ b/src/map/npc.hpp @@ -1219,6 +1219,7 @@ void do_clear_npc(void); void do_final_npc(void); void do_init_npc(void); void npc_event_do_oninit(void); +const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath); int npc_event_do(const char* name); int npc_event_do_id(const char* name, int rid); diff --git a/src/map/script.cpp b/src/map/script.cpp index 604274ecd..9da5d4690 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -24548,6 +24548,38 @@ BUILDIN_FUNC(preg_match) { #endif } +BUILDIN_FUNC(duplicate) +{ + const char *map = script_getstr(st,2); + int x = script_getnum(st,3); + int y = script_getnum(st,4); + int dir = script_getnum(st,5); + const char *duplicate_name = script_getstr(st,6); + const char *npc_name = script_getstr(st,7); + char w1[2048], w2[2048], w3[2048], w4[2048], p[2048]; + int view_id = script_getnum(st,8); + struct npc_data* nd = map_id2nd(st->oid); + + if (!nd) { + return SCRIPT_CMD_FAILURE; + } + + sprintf(w1, "%s,%d,%d,%d", map, x, y, dir); + sprintf(w2, "duplicate(%s)", duplicate_name); + sprintf(w3, "%s", npc_name); + + if (script_hasdata(st,9) && script_hasdata(st,10)) { + sprintf(w4, "%d,%d,%d", view_id, script_getnum(st,9), script_getnum(st,10)); + } + else { + sprintf(w4, "%d", view_id); + } + + sprintf(p, "%s\t%s\t%s\t%s", w1, w2, w3, w4); + npc_parse_duplicate(w1,w2,w3,w4, p, p, nd->path); + return SCRIPT_CMD_SUCCESS; +} + /// script command definitions /// for an explanation on args, see add_buildin_func struct script_function buildin_func[] = { @@ -25170,6 +25202,8 @@ struct script_function buildin_func[] = { BUILDIN_DEF(achievement_condition,"i"), BUILDIN_DEF(getvariableofinstance,"ri"), BUILDIN_DEF(convertpcinfo,"vi"), + + BUILDIN_DEF(duplicate,"siiissi??"), #include "../custom/script_def.inc" {NULL,NULL,NULL},
  4. 123.jpg

    Pretty sure the script is right, but either way before i used to be able to test it but all i get is this error 

  5. That means you tried to use the close command when there was no text being displayed (from the mes command). I... don't know what NPC this is, but you'll want to change that "close" for "end" instead.
  6. Heya, The job names are hard-coded in the client executable. You'll have to open an hex editor and then search for "Gunslinger".
  7. Yes, when you "receive" the item in your inventory, the button will display properly because it uses the clif_additem packet. I meant how you receive the item information packet-wise, not the source of where it came from (though that's related of course). As for why 20285 shows up and 20286 doesn't, that is because 20285 has a hat effect and these are not displayed on the client with the feature. You can remove the item from the list by opening hateffectinfo.lub and then removing the ids from effectHatItemTable. It's probably best to keep the button disabled for that one though.
  8. Heya, These are ground unit skills. You'll want to skip the BL_PC check and then adjust the skill ratios to battle.cpp: diff --git a/src/map/battle.cpp b/src/map/battle.cpp index de8167f4a..904a672d8 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -4354,6 +4354,13 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list * if (sd && pc_checkskill(sd, SU_SPIRITOFLIFE)) skillratio += skillratio * status_get_hp(src) / status_get_max_hp(src); break; + case SG_SUN_WARM: + case SG_MOON_WARM: + case SG_STAR_WARM: + if (tsd) { + skillratio += -50; + } + break; } return skillratio; } diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 3b7b4ba86..7656a247f 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -13795,7 +13795,7 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, t_t do { if( bl->type == BL_PC ) status_zap(bl, 0, 15); // sp damage to players - else // mobs + if( status_charge(ss, 0, 2) ) { // costs 2 SP per hit if( !skill_attack(BF_WEAPON,ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick+(t_tick)count*sg->interval,0) ) status_charge(ss, 0, 8); //costs additional 8 SP if miss
  9. Heya, I presume you're talking about the "Preview" button from the item descriptions? If so, then it's not a file, this is decided server-side. How you receive the item makes the button appear or not. If you look in the clif_vendinglist function, you'll see some item packets sent to the client have 6 extra bytes. This part in particular: WFIFOL(fd,offset+47+i*item_length) = pc_equippoint_sub(sd,data); WFIFOW(fd,offset+51+i*item_length) = data->look; The data->look is the actual view ID that will be shown on the client for the item after clicking the button. The pc_equippoint_sub decides whether the client should display the button or not. The problem with that system is that many packets don't have that feature. If you try to preview the item from a shop NPC, it won't give you the option either. If you put the item in your cart, the button will disappear as well, etc. It's just very unreliable overall. kRO added more "locations" where this feature is available, though.
  10. Tokei

    Picklog db

    Heya, You'll need to edit log_pick in log.cpp: void log_pick(int id, int16 m, e_log_pick_type type, int amount, struct item* itm) Something along those lines: /// logs item transactions (generic) void log_pick(int id, int16 m, e_log_pick_type type, int amount, struct item* itm) { nullpo_retv(itm); if( ( log_config.enable_logs&type ) == 0 ) {// disabled return; } if( !should_log_item(itm->nameid, amount, itm->refine) ) return; //we skip logging this item set - it doesn't meet our logging conditions [Lupus] if( log_config.sql_logs ) { int i; struct map_session_data *sd = map_charid2sd(id); SqlStmt* stmt = SqlStmt_Malloc(logmysql_handle); char esc_sname[NAME_LENGTH*2+1]; StringBuf buf; StringBuf_Init(&buf); if (sd) { Sql_EscapeStringLen(logmysql_handle, esc_sname, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)); } StringBuf_Printf(&buf, "%s INTO `%s` (`time`, `char_id`, `account_id`, `name`, `type`, `nameid`, `amount`, `refine`, `map`, `unique_id`, `bound`", LOG_QUERY, log_config.log_pick); for (i = 0; i < MAX_SLOTS; ++i) StringBuf_Printf(&buf, ", `card%d`", i); for (i = 0; i < MAX_ITEM_RDM_OPT; ++i) { StringBuf_Printf(&buf, ", `option_id%d`", i); StringBuf_Printf(&buf, ", `option_val%d`", i); StringBuf_Printf(&buf, ", `option_parm%d`", i); } StringBuf_Printf(&buf, ") VALUES(NOW(),'%u','%u','%s','%c','%d','%d','%d','%s','%" PRIu64 "','%d'", id, sd ? sd->status.account_id : 0, sd ? esc_sname : "", log_picktype2char(type), itm->nameid, amount, itm->refine, map_getmapdata(m)->name[0] ? map_getmapdata(m)->name : "", itm->unique_id, itm->bound); for (i = 0; i < MAX_SLOTS; i++) StringBuf_Printf(&buf, ",'%d'", itm->card[i]); for (i = 0; i < MAX_ITEM_RDM_OPT; i++) StringBuf_Printf(&buf, ",'%d','%d','%d'", itm->option[i].id, itm->option[i].value, itm->option[i].param); StringBuf_Printf(&buf, ")"); if (SQL_SUCCESS != SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) || SQL_SUCCESS != SqlStmt_Execute(stmt)) SqlStmt_ShowDebug(stmt); SqlStmt_Free(stmt); StringBuf_Destroy(&buf); } else { char timestring[255]; time_t curtime; FILE* logfp; if( ( logfp = fopen(log_config.log_pick, "a") ) == NULL ) return; time(&curtime); strftime(timestring, sizeof(timestring), log_timestamp_format, localtime(&curtime)); fprintf(logfp,"%s - %d\t%c\t%hu,%d,%d,%hu,%hu,%hu,%hu,%s,'%" PRIu64 "',%d\n", timestring, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map_getmapdata(m)->name[0]?map_getmapdata(m)->name:"", itm->unique_id, itm->bound); fclose(logfp); } }
  11. Heya, You can't do that (not without major changes anyway). I presume the goal here is to run a script in the source (which is a bad idea), but the easy solution here would simply be to set your variables as temporary global variables and then run an event label: In the source, you would use something like: #include "mapreg.h" #include "npc.h" [...] mapreg_setreg(reference_uid(add_str("[email protected]"), 0), MG_SAFETYWALL); mapreg_setreg(reference_uid(add_str("[email protected]"), 0), skill_id); mapreg_setregstr(reference_uid(add_str("[email protected]$"), 0), "a string"); npc_event_do_id("MyScript::OnCalled", sd->bl.id); And in the script: function script myfunction { announce "arg1: " + getarg(0) + ", arg2: " + getarg(1) + ", arg3: " + getarg(2); return; } - script MyScript -1,{ end; OnCalled: callfunc("myfunction", [email protected], [email protected], [email protected]$); end; } It would be much easier to do the code in the source directly instead though.
  12. Heya, You can use Scripts > Magnifier. It's a multiplier, so simply use a number below 1 to make it smaller.
  13. Heya, Your files are encrypted and they cannot be read/extracted from the GRF. That is the purpose of an encryption tool. Your GRF is not locked in any way. It can be merged, it can be patched, it can be modified, etc. It's meant to protect your work, sprites, custom maps, etc. What you're looking for is an anti-cheat software and this is not one...!
  14. Heya, There are no built-in tool for what you want to do, so you have to write it yourself from the script tool. The property you're looking for in your case is "SpriteIndex": foreach (var action in act) { foreach (var frame in action) { foreach (var layer in frame){ if (layer.SpriteIndex == 0 || layer.SpriteIndex == 1 || layer.SpriteIndex == 2 || layer.SpriteIndex == 9) { layer.OffsetY += 10; } } } } // or act.AllLayers(layer => { if (layer.SpriteIndex == 0 || layer.SpriteIndex == 1 || layer.SpriteIndex == 2 || layer.SpriteIndex == 9) { layer.OffsetY += 10; } }); // or foreach (var layer in act.GetAllLayers()) { if (layer.SpriteIndex == 0 || layer.SpriteIndex == 1 || layer.SpriteIndex == 2 || layer.SpriteIndex == 9) { layer.OffsetY += 10; } }
  15. Heya, Use the latest vesion (from the mediafire links), it supports the costume key...!