// marriage npc // allows to marry other players // * must be duplicated - script marriage NPC_NO_SPRITE,{ end; function toPlayer { // send a message to the player .previous = playerattached(); // attachrid is required because we want to use l() on another player attachrid(getarg(1, getcharid(CHAR_ID_ACCOUNT))); dispbottom(b(l(getarg(0)))); attachrid(.previous); return; } function _officiator { // make the wedding officiator say a message if (getarg(1, 0)) { // only send to the target player unittalk(.officiator, l(getarg(0)), true, SELF, getarg(1, getcharid(CHAR_ID_ACCOUNT))); } else { // regular npctalk unittalk(.officiator, getarg(0), true); } return; } function officiator { if (.officiator) { return _officiator(getarg(0)); } else { toPlayer(getarg(0)); if (getarg(1, 0)) { toPlayer(getarg(0), getarg(1)); } return; } } function explain { // send an explanation message if (.officiator) { return _officiator(getarg(0), playerattached()); } else { return toPlayer(getarg(0)); } } function do_marriage { if (.officiator) { // let the officiator handle it @marriage$ = getarg(0); doevent(.officiator$ + "::OnDoMarriage"); } else { // no officiator marriage(getarg(0)); announce(sprintf("%s and %s are now married!", strcharinfo(PC_NAME), getarg(0)), bc_all); } return; } OnCheckWord: .@verb$ = strtolower($@p1$); if (.@verb$ != "marry" && .@verb$ != l("marry")) { end; // ignore } // get the location of the invoking character getmapxy(.@map$, .@x, .@y, UNITTYPE_PC); if (.@map$ != .map$ || .@x < .x1 || .@x > .x2 || .@y < .y1 || .@y > .y2) { explain("You must stand in the designated area"); end; } // check if the target character exists and is online .@target$ = $@p2$; .@target = getcharid(CHAR_ID_ACCOUNT, .@target$); if (.@target == 0) { explain(sprintf("Player %s doesn't exist or is offline", .@target$)); end; } if (.@target == playerattached()) { explain("You cannot marry yourself"); end; } // get the location of the target character getmapxy(.@map$, .@x, .@y, UNITTYPE_PC, .@target); if (.@map$ != .map$ || .@x < .x1 || .@x > .x2 || .@y < .y1 || .@y > .y2) { explain("Your partner must stand in the designated area"); end; } if (BaseLevel < WEDDING_MIN_LEVEL || readparam(BaseLevel, .@target) < WEDDING_MIN_LEVEL) { explain(sprintf("You and your partner must be at least level %i to marry", WEDDING_MIN_LEVEL)); end; } // XXX: do we want to check for wedding rings? if (!isequipped(WeddingRing)) { explain("You must be wearing a %s to marry.", getitemname(WeddingRing)); end; } if (getpartnerid()) { if (getpartnerid() == getcharid(CHAR_ID_CHAR, .@target$)) { explain("You are already married to this person."); } else { explain("You are already married to someone else."); } end; } if (getvariableofpc(@marriage, .@target, 0) == getcharid(CHAR_ID_CHAR)) { // the target already requested to marry us if (getvariableofpc(@marriage[1], .@target, 0) > now()) { // You must be wearing a wedding ring at all times if (!isequipped(WeddingRing)) { explain("You must be wearing a %s to marry.", getitemname(WeddingRing)); end; } // marriage request has not expired: procceed to marry do_marriage(.@target$); end; } else { // marriage request expired explain("This marriage proposal has expired. Please try again"); // refresh our own expiration @marriage = getcharid(CHAR_ID_CHAR, .@target$); @marriage[1] = time_from_minutes(+15); // expiration } } else if (@marriage && @marriage[1] > now()) { // we already initiated a marriage request if (@marriage == getcharid(CHAR_ID_CHAR, .@target$)) { explain("You are already marrying this person."); @marriage[1] = time_from_minutes(+15); // refresh expiration } else { // already marrying someone else? explain("You are already in the process of marrying someone else."); explain(sprintf("Are you sure you wish to marry %s?", .@target$)); explain(sprintf("To confirm, type the same message again: %s %s", $@p1$, $@p2$)); @marriage = 0; // clear the current target } } else { // initiate a new marriage request @marriage = getcharid(CHAR_ID_CHAR, .@target$); @marriage[1] = time_from_minutes(+15); // expiration announce(sprintf("%s is asking %s for marriage!", strcharinfo(PC_NAME), .@target$), bc_all); officiator(sprintf("%s, to accept this marriage proposal, say: marry %s", .@target$, strcharinfo(PC_NAME)), .@target); } end; OnInit: if (strnpcinfo(NPC_MAP) == "") { // this is not a duplicate end; } explode(.@hidden$, strnpcinfo(NPC_NAME_HIDDEN), "#"); explode(.@area$, .@hidden$[getarraysize(.@hidden$) - 1], ","); switch (getarraysize(.@area$)) { case 1: if (.@area$[0] == "") { .@d = 3; } else { .@d = atoi(.@area$[0]); } .x1 = .x - .@d; .x2 = .x + .@d; .y1 = .y - .@d; .y2 = .y + .@d; break; case 2: .@dx = atoi(.@area$[0]); .@dy = atoi(.@area$[1]); .x1 = .x - .@dx; .x2 = .x + .@dx; .y1 = .y - .@dy; .y2 = .y + .@dy; break; case 4: .x1 = atoi(.@area$[0]); .x2 = atoi(.@area$[2]); .y1 = atoi(.@area$[1]); .y2 = atoi(.@area$[3]); break; default: consolemes(CONSOLEMES_ERROR, "unexpected number of arguments for the marriage duplicate"); break; } // now find the wedding officiator (if any) .@count = getunits(BL_NPC, .@units, false, strnpcinfo(NPC_MAP)); freeloop(true); for (.@i = 0; .@i < .@count; ++.@i) { .@name$ = strtolower(strnpcinfo(NPC_NAME_HIDDEN, "", .@units[.@i])); .@full$ = strnpcinfo(NPC_NAME, "", .@units[.@i]); if (getnpcsubtype(.@units[.@i]) != NPCSUBTYPE_SCRIPT) { // getunits() doesn't filter npc subtypes continue; } if (endswith(.@name$, "officiator") || endswith(.@name$, "marriage") || endswith(.@name$, "wedding") || getvariableofnpc(.officiator, .@full$) || getvariableofnpc(.marriage, .@full$) || getvariableofnpc(.wedding, .@full$)) { .officiator = .@units[.@i]; .officiator$ = .@full$; break; } } freeloop(false); defpattern(.id, "^.+ : (?:##[0-9aBb])?([A-Za-z]+) (.{4,23})$", "OnCheckWord"); activatepset(.id); .distance = 14; end; } // to use, create a duplicate: //001-1,30,31,0 duplicate(marriage) name#x1,y1,x2,y2 NPCID //001-1,30,31,0 duplicate(marriage) name#range NPCID