public CharacterWorldLogin(Character c) : base(0x71, 28) { string mapname = Map.GetClientName(c.LastPoint.Map.Name); Write((int)c.Serial.Value); Write(mapname, Core.Conf.General.GetInt("MaxMapNameClientLength")); Write((int)Core.Connector.Listener.IPs[0].Address); Write((short)Core.Connector.Listener.Ports[0]); }
public CharacterResponseWorldLogin(Character c) : base(0x71, 28) { string mapname = Map.GetClientName(c.Status.Location.Map.Name); Write((uint)c.WorldID.ID); Write(mapname, Global.MAP_NAME_LENGTH_EXT); Write((int)Core.Connector.Listener.IPs[0].GetAddress()); Write((short)Core.Connector.Listener.Ports[0]); }
public WorldWalkOK(Character c) : base(0x87, 11) { Write((int)DateTime.Now.Ticks); Write(c.Location.Point, c.TargetLocation, new Point2D(8, 8)); }
/*========================================== * Fetches a random mobID * type: Where to fetch from: * 0: dead branch list * 1: poring list * 2: bloody branch list * flag: * &1: Apply the summon success chance found in the list (otherwise get any monster from the db) * &2: Apply a monster check level. * &4: Selected monster should not be a boss type * &8: Selected monster must have normal spawn. * lv: Mob level to check against *------------------------------------------*/ public static int GetRandomMobID(Character character, int type, int flag, int lv) { int mobID = 0; // TODO: implement me q.q /* do { if (type > 0) class_ = summon[type].class_[rand()%summon[type].qty]; else //Dead branch class_ = rand() % MAX_MOB_DB; mob = mob_db(class_); } while ((mob == mob_dummy || mob_is_clone(class_) || (flag&1 && mob->summonper[type] <= rand() % 1000000) || (flag&2 && lv < mob->lv) || (flag&4 && mob->status.mode&MD_BOSS) || (flag&8 && mob->spawn[0].qty < 1) ) && (i++) < MAX_MOB_DB); if(i >= MAX_MOB_DB) // no suitable monster found, use fallback for given list class_ = mob_db_data[0]->summonper[type]; */ return mobID; }
private static Monster SpawnOnceSub(Character character, Location loc, string name, int mobID) { // Create new world object based on mobID Monster mob = new Monster(new DatabaseID(mobID, EDatabaseType.Mob)); // Search free cell to spawn, if no given Point2D spawnPoint = loc.Point; if (character != null && (spawnPoint.X < 0 || spawnPoint.Y < 0)) { // if none found, pick random position on map if (loc.Map.SearchFreeCell(character, ref spawnPoint, 1, 1, 0) == false) { if (spawnPoint.X <= 0 || spawnPoint.Y <= 0 || loc.Map.CheckCell(spawnPoint, ECollisionType.Reachable) == false) { // Failed to fetch random spot on the whole map? if (loc.Map.SearchFreeCell(null, ref spawnPoint, -1, -1, 1) == false) { ServerConsole.ErrorLine("SpawnSub: Failed to locate spawn pos on map " + loc.Map.Name); return null; } } } } mob.Location = new Location(loc.Map.ID, spawnPoint); mob.Name = name; mob.Class = (short)mobID; // mob_parse_dataset here; check for tiny/large, event and so on // TODO: takeover of special_state AI ect; need mob_parse_dataset before // and place in Monster class to store it (look @ eA mob_data) mob.ViewData = WorldObjectViewData.GetViewData(mob.Database, mobID); mob.Status = new WorldObjectStatus(mob); mob.BaseStatus = new WorldObjectStatus(mob); mob.StatusChange.Clear(); return mob; }
public CharacterResponseNewData(Character c) : base(0x6d) { c.ToStream(Writer); }
private uint CalculateBasePcMaxSP(Character character, WorldObjectStatus status) { return 0; }
/// <summary>Executes the warp action.</summary> /// <param name="target">Target for the warp.</param> public virtual void OnWarp(Character target) { // TODO: basic warp }
/// <summary> /// Callback for executing an action (attack/sit/stand) to a target (ID) /// </summary> /// <param name="character"></param> /// <param name="action"></param> /// <param name="id"></param> private static void Callback_ActionRequest(Character character, byte action, int id) { // TODO: check for dead player // TODO: check for trickdead, autocounter or bladestop (no action available) character.StopWalking(0x1); character.StopAttack(); // For disguise if (id < 0 && -id == character.AccountID) { id = (int)character.AccountID; } switch (action) { case 0x0: // Attack once case 0x7: // Attack continue if (character.CantAct() == false || (character.StatusChange.Option & EStatusOption.Hide) > 0) { return; } EStatusOption badOptions = (EStatusOption.Wedding | EStatusOption.Xmas | EStatusOption.Summer); if ((character.StatusChange.Option & badOptions) > 0) { return; } // TODO: basilica // TODO: freecast check character.ResetInvisibleTimer(); character.Attack(id, (action != 0x0)); break; case 0x02: // sitdown /* if (battle_config.basic_skill_check && pc_checkskill(sd, NV_BASIC) < 3) { clif_skill_fail(sd, 1, 0, 2); break; } */ if (character.IsSit() == true) { // Bugged client? Just refresh them World.Send(new WorldUnitSitStand(character, true), character, ESendTarget.Area); return; } if (Timer.IsValid(character.ActiveSkillTimer) == true || character.StatusChange.Option1 != EStatusOption1.None) { break; } /* if (sd->sc.count && ( sd->sc.data[SC_DANCING] || (sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) )) //No sitting during these states either. break; */ character.SetSit(); //skill_sit(sd, 1); World.Send(new WorldUnitSitStand(character, true), character, ESendTarget.Area); break; case 0x03: // standup if (character.IsSit() == false) { World.Send(new WorldUnitSitStand(character, false), character, ESendTarget.Area); return; } character.SetStand(); //skill_sit(sd, 0); World.Send(new WorldUnitSitStand(character, false), character, ESendTarget.Area); break; } }
public NewCharacterData(Character c) : base(0x6d) { c.ToStream(Writer); }
public static ECharacterCreationResult Create(Account account, string name, byte slot, byte str, byte agi, byte vit, byte int_, byte dex, byte luk, short hairColor, short hairStyle, out Character newChar) { newChar = null; if (name.Length > 24) { name = name.Substring(0, 24); } //name = name.Replace('\032', ' ').Replace('\t', ' ').Replace('\x0A', ' ').Replace('\x0D', ' '); if ( (slot >= Global.MAX_SLOTS) || (str + agi + vit + int_ + dex + luk != 6 * 5) || (str < 1 || str > 9 || agi < 1 || agi > 9 || vit < 1 || vit > 9 || int_ < 1 || int_ > 9 || dex < 1 || dex > 9 || luk < 1 || luk > 9) || (str + int_ != 10 || agi + luk != 10 || vit + dex != 10) ) { return ECharacterCreationResult.CharCreationDenied; // invalid input } // Check for max character count on this account if (account.Chars.Count >= Global.MAX_SLOTS) { return ECharacterCreationResult.CharCreationDenied; // character account limit exceeded } // Check for existing char with this name if (Core.Database.Query("SELECT charID FROM `char` WHERE `name` = '{0}'", name.MysqlEscape()).Rows.Count > 0) { return ECharacterCreationResult.CharnameAlreadyExists; } // Check for existing char on this slot foreach (Character tmpChar in account.Chars.Values) { if (tmpChar.Status.Slot == slot) { return ECharacterCreationResult.CharCreationDenied; } } // TODO: this has to be in CharacterDatabaseStatus, nor? // CharacterDatabaseData represents the character in the character server // so.. newChar = new Character(DatabaseID.Zero, false); newChar.Parent = account; newChar.Status.Name = name; newChar.Status.Slot = slot; newChar.Status.Zeny = Config.StartZeny; newChar.Status.Str = str; newChar.Status.Agi = agi; newChar.Status.Dex = dex; newChar.Status.Vit = vit; newChar.Status.Int = int_; newChar.Status.Luk = luk; newChar.Status.HPMax = newChar.Status.HP = (40 * (100 + vit) / 100); newChar.Status.SPMax = newChar.Status.SP = (11 * (100 + int_) / 100); newChar.Status.HairStyle = hairStyle; newChar.Status.HairColor = hairColor; newChar.Status.SavePoint = new Location(Mapcache.GetID(Config.StartMap), Config.StartMapX, Config.StartMapY); newChar.Status.Location = new Location(newChar.Status.SavePoint.Map.ID, newChar.Status.SavePoint.Point.X, newChar.Status.SavePoint.Point.Y); // Save it CharacterDatabaseData status = newChar.Status; string query = string.Format( "INSERT INTO `char` (" + "`accountID`, `slot`, `name`, `zeny`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hpMax`, `hp`," + "`spMax`, `sp`, `hair`, `hairColor`, `lastMap`, `lastX`, `lastY`, `saveMap`, `saveX`, `saveY`" + ") VALUES (" + "{0}, {1}, '{2}', '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', '{10}', '{11}'," + "'{12}', '{13}', '{14}', '{15}', '{16}', '{17}', '{18}', '{19}', '{20}', '{21}'" + ")" , account.WorldID.ID, slot, name.MysqlEscape(), status.Zeny, status.Str, status.Agi, status.Vit, status.Int, status.Dex, status.Luk, status.HPMax, status.HP, status.SPMax, status.SP, status.HairStyle, status.HairColor, status.Location.Map, status.Location.Point.X, status.Location.Point.Y, status.SavePoint.Map, status.SavePoint.Point.X, status.SavePoint.Point.X ); Core.Database.Query(query); uint charID = (uint)Core.Database.GetLastInsertID(); if (charID == 0) { // Failed to add character? return ECharacterCreationResult.CharCreationDenied; } // save Serial/CharID newChar.UpdateDatabaseID(charID, EDatabaseType.Char); newChar.WorldID = new WorldID(charID, EDatabaseType.Char); // Add it to account dictionary account.Chars.Add(newChar.WorldID, newChar); return ECharacterCreationResult.Success; }
public static Character Load(Account account, DataRow row) { Character c = new Character(DatabaseID.Zero, false); // Load basic character data c.Status = new CharacterDatabaseData(row); // Update WorldID (same as Serial/DatabaseID) c.WorldID = new WorldID(c.Status.Serial.ID, c.Status.Serial.Type); // Update location c.Location = c.Status.Location; // Update account c.Parent = account; return c; }
/// <summary>Executes the touch action.</summary> /// <param name="target">Target for the touch.</param> public virtual void OnTouch(Character target) { }
/// <summary>Executes the click action.</summary> /// <param name="target">Target for the click.</param> public virtual void OnClick(Character target) { }