public void HandleBoyancy(Vec3d pos, Vec3f velocity, bool boyant, float gravityStrength, float deltatime, float height) { int xPrev = (int)pos.X; int yPrev = (int)pos.Y; int zPrev = (int)pos.Z; tmpPos.Set(xPrev, yPrev, zPrev); Block block = BlockAccess.GetBlock(tmpPos); Block prevBlock = block; if (block == null) { return; } if (boyant) { if (block.IsLiquid()) { tmpPos.Set(xPrev, (int)(pos.Y + 1), zPrev); block = BlockAccess.GetBlock(tmpPos); if (block == null) { return; } float waterY = (int)pos.Y + prevBlock.LiquidLevel / 8f + (block.IsLiquid() ? 9 / 8f : 0); float bottomSubmergedness = waterY - (float)pos.Y; float swimlineSubmergedness = GameMath.Clamp(bottomSubmergedness + height, 0, 1); float boyancyStrength = GameMath.Clamp(9 * swimlineSubmergedness, -1.25f, 1.25f); // was 3* before. Dunno why it has to be 9* now velocity.Y += gravityStrength * deltatime * boyancyStrength; float waterDrag = (float)GameMath.Clamp(30 * Math.Abs(velocity.Y) - 0.02f, 1, 1.25f); velocity.Y /= waterDrag; velocity.X *= 0.99f; velocity.Z *= 0.99f; if (prevBlock.PushVector != null && swimlineSubmergedness >= 0) { float factor = deltatime / (33f / 1000f); velocity.Add( (float)prevBlock.PushVector.X * 15 * factor, (float)prevBlock.PushVector.Y * 15 * factor, (float)prevBlock.PushVector.Z * 15 * factor ); } } } else { if (block.PushVector != null) { velocity.Add( (float)block.PushVector.X * 30 * deltatime, (float)block.PushVector.Y * 30 * deltatime, (float)block.PushVector.Z * 30 * deltatime ); } } }
/// <summary> /// For placement of ruins during worldgen, replaces the topsoil with the area specific soil (e.g. sand) /// </summary> /// <param name="blockAccessor"></param> /// <param name="blocks"></param> /// <param name="startPos"></param> /// <param name="climateUpLeft"></param> /// <param name="climateUpRight"></param> /// <param name="climateBotLeft"></param> /// <param name="climateBotRight"></param> /// <param name="replaceblockids"></param> /// <returns></returns> public int PlaceRespectingBlockLayers(IBlockAccessor blockAccessor, IWorldAccessor worldForCollectibleResolve, BlockPos startPos, int climateUpLeft, int climateUpRight, int climateBotLeft, int climateBotRight, ushort[] replaceblockids) { BlockPos curPos = new BlockPos(); int placed = 0; int chunksize = blockAccessor.ChunkSize; for (int x = 0; x < SizeX; x++) { for (int z = 0; z < SizeZ; z++) { curPos.Set(x + startPos.X, startPos.Y, z + startPos.Z); ushort rockblockid = blockAccessor.GetMapChunkAtBlockPos(curPos).TopRockIdMap[(curPos.Z % chunksize) * chunksize + curPos.X % chunksize]; int depth = 0; for (int y = SizeY - 1; y >= 0; y--) { curPos.Set(x + startPos.X, y + startPos.Y, z + startPos.Z); Block newBlock = blocksByPos[x, y, z]; if (newBlock == null) { continue; } if (newBlock.Replaceable < 1000) { if (replaceblockids.Length > depth && newBlock.BlockId == replaceblockids[depth]) { int climate = GameMath.BiLerpRgbColor((float)x / chunksize, (float)z / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); newBlock = GetBlockLayerBlock((climate >> 8) & 0xff, (climate >> 16) & 0xff, startPos.Y, rockblockid, depth, newBlock, worldForCollectibleResolve.Blocks); } depth++; } Block oldBlock = blockAccessor.GetBlock(curPos); placed += handler(blockAccessor, curPos, oldBlock, newBlock); byte[] lightHsv = newBlock.GetLightHsv(blockAccessor, curPos); if (lightHsv[2] > 0 && blockAccessor is IWorldGenBlockAccessor) { int chunkSize = blockAccessor.ChunkSize; ((IWorldGenBlockAccessor)blockAccessor).ScheduleBlockLightUpdate(curPos.Copy(), oldBlock.BlockId, newBlock.BlockId); } } } } foreach (var val in BlockEntities) { uint index = val.Key; int dx = (int)(index & 0x1ff); int dy = (int)((index >> 20) & 0x1ff); int dz = (int)((index >> 10) & 0x1ff); curPos.Set(startPos.X + dx, startPos.Y + dy, startPos.Z + dz); BlockEntity be = blockAccessor.GetBlockEntity(curPos); if (be != null) { be.FromTreeAtributes(DecodeBlockEntityData(val.Value), worldForCollectibleResolve); be.OnLoadCollectibleMappings(worldForCollectibleResolve, BlockCodes, ItemCodes); be.pos = curPos.Copy(); } } return(placed); }
/// <summary> /// Checks the Positive Spells. Handles buffs, heals, etc. /// </summary> protected override bool CheckDefensiveSpells(Spell spell) { if (spell == null || spell.IsHarmful) { return(false); } // Make sure we're currently able to cast the spell if (spell.CastTime > 0 && (Body.IsCasting || (Body.IsBeingInterrupted && !spell.Uninterruptible))) { return(false); } // Make sure the spell isn't disabled if (spell.HasRecastDelay && Body.GetSkillDisabledDuration(spell) > 0) { return(false); } bool casted = false; // clear current target, set target based on spell type, cast spell, return target to original target GameObject lastTarget = Body.TargetObject; Body.TargetObject = null; GamePlayer player = null; GameLiving owner = null; switch (spell.SpellType.ToUpper()) { #region Buffs case "ACUITYBUFF": case "AFHITSBUFF": case "ALLMAGICRESISTSBUFF": case "ARMORABSORPTIONBUFF": case "ARMORFACTORBUFF": case "BODYRESISTBUFF": case "BODYSPIRITENERGYBUFF": case "BUFF": case "CELERITYBUFF": case "COLDRESISTBUFF": case "COMBATSPEEDBUFF": case "CONSTITUTIONBUFF": case "COURAGEBUFF": case "CRUSHSLASHTHRUSTBUFF": case "DEXTERITYBUFF": case "DEXTERITYQUICKNESSBUFF": case "EFFECTIVENESSBUFF": case "ENDURANCEREGENBUFF": case "ENERGYRESISTBUFF": case "FATIGUECONSUMPTIONBUFF": case "FELXIBLESKILLBUFF": case "HASTEBUFF": case "HEALTHREGENBUFF": case "HEATCOLDMATTERBUFF": case "HEATRESISTBUFF": case "HEROISMBUFF": case "KEEPDAMAGEBUFF": case "MAGICRESISTSBUFF": case "MATTERRESISTBUFF": case "MELEEDAMAGEBUFF": case "MESMERIZEDURATIONBUFF": case "MLABSBUFF": case "PALADINARMORFACTORBUFF": case "PARRYBUFF": case "POWERHEALTHENDURANCEREGENBUFF": case "POWERREGENBUFF": case "SAVAGECOMBATSPEEDBUFF": case "SAVAGECRUSHRESISTANCEBUFF": case "SAVAGEDPSBUFF": case "SAVAGEPARRYBUFF": case "SAVAGESLASHRESISTANCEBUFF": case "SAVAGETHRUSTRESISTANCEBUFF": case "SPIRITRESISTBUFF": case "STRENGTHBUFF": case "STRENGTHCONSTITUTIONBUFF": case "SUPERIORCOURAGEBUFF": case "TOHITBUFF": case "WEAPONSKILLBUFF": case "DAMAGEADD": case "OFFENSIVEPROC": case "DEFENSIVEPROC": case "DAMAGESHIELD": case "BLADETURN": { String target; //Buff self if (!LivingHasEffect(Body, spell)) { Body.TargetObject = Body; break; } target = spell.Target.ToUpper(); if (target == "SELF") { break; } if (target == "REALM" || target == "GROUP") { owner = (this as IControlledBrain).Owner; player = null; //Buff owner if (!LivingHasEffect(owner, spell) && GameMath.IsWithinRadius(Body, owner, spell.Range)) { Body.TargetObject = owner; break; } if (owner is GameNPC npc) { //Buff other minions foreach (IControlledBrain icb in npc.ControlledNpcList) { if (icb != null && icb.Body != null && !LivingHasEffect(icb.Body, spell) && GameMath.IsWithinRadius(Body, icb.Body, spell.Range)) { Body.TargetObject = icb.Body; break; } } } player = GetPlayerOwner(); //Buff player if (player != null) { if (!LivingHasEffect(player, spell)) { Body.TargetObject = player; break; } if (player.Group != null) { foreach (GamePlayer p in player.Group.GetPlayersInTheGroup()) { if (!LivingHasEffect(p, spell) && GameMath.IsWithinRadius(Body, p, spell.Range)) { Body.TargetObject = p; break; } } } } } } break; #endregion Buffs #region Disease Cure/Poison Cure/Summon case "CUREDISEASE": //Cure owner owner = (this as IControlledBrain).Owner; if (owner.IsDiseased) { Body.TargetObject = owner; break; } //Cure self if (Body.IsDiseased) { Body.TargetObject = Body; break; } // Cure group members player = GetPlayerOwner(); if (player.Group != null) { foreach (GamePlayer p in player.Group.GetPlayersInTheGroup()) { if (p.IsDiseased && GameMath.IsWithinRadius(Body, p, spell.Range)) { Body.TargetObject = p; break; } } } break; case "CUREPOISON": //Cure owner owner = (this as IControlledBrain).Owner; if (LivingIsPoisoned(owner)) { Body.TargetObject = owner; break; } //Cure self if (LivingIsPoisoned(Body)) { Body.TargetObject = Body; break; } // Cure group members player = GetPlayerOwner(); if (player.Group != null) { foreach (GamePlayer p in player.Group.GetPlayersInTheGroup()) { if (LivingIsPoisoned(p) && GameMath.IsWithinRadius(Body, p, spell.Range)) { Body.TargetObject = p; break; } } } break; case "SUMMON": Body.TargetObject = Body; break; #endregion #region Heals case "COMBATHEAL": case "HEAL": case "HEALOVERTIME": case "MERCHEAL": case "OMNIHEAL": case "PBAEHEAL": case "SPREADHEAL": String spellTarget = spell.Target.ToUpper(); int bodyPercent = Body.HealthPercent; if (spellTarget == "SELF") { if (bodyPercent < GS.ServerProperties.Properties.NPC_HEAL_THRESHOLD && !spell.TargetHasEffect(Body)) { Body.TargetObject = Body; } break; } // Heal seriously injured targets first int emergencyThreshold = GS.ServerProperties.Properties.NPC_HEAL_THRESHOLD / 2; //Heal owner owner = (this as IControlledBrain).Owner; int ownerPercent = owner.HealthPercent; if (ownerPercent < emergencyThreshold && !spell.TargetHasEffect(owner) && GameMath.IsWithinRadius(Body, owner, spell.Range)) { Body.TargetObject = owner; break; } //Heal self if (bodyPercent < emergencyThreshold && !spell.TargetHasEffect(Body)) { Body.TargetObject = Body; break; } // Heal group player = GetPlayerOwner(); ICollection <GamePlayer> playerGroup = null; if (player.Group != null && (spellTarget == "REALM" || spellTarget == "GROUP")) { playerGroup = player.Group.GetPlayersInTheGroup(); foreach (GamePlayer p in playerGroup) { if (p.HealthPercent < emergencyThreshold && !spell.TargetHasEffect(p) && GameMath.IsWithinRadius(Body, p, spell.Range)) { Body.TargetObject = p; break; } } } // Now check for targets which aren't seriously injured if (spellTarget == "SELF") { // if we have a self heal and health is less than 75% then heal, otherwise return false to try another spell or do nothing if (bodyPercent < GS.ServerProperties.Properties.NPC_HEAL_THRESHOLD && !spell.TargetHasEffect(Body)) { Body.TargetObject = Body; } break; } //Heal owner owner = (this as IControlledBrain).Owner; if (ownerPercent < GS.ServerProperties.Properties.NPC_HEAL_THRESHOLD && !spell.TargetHasEffect(owner) && GameMath.IsWithinRadius(Body, owner, spell.Range)) { Body.TargetObject = owner; break; } //Heal self if (bodyPercent < GS.ServerProperties.Properties.NPC_HEAL_THRESHOLD && !spell.TargetHasEffect(Body)) { Body.TargetObject = Body; break; } // Heal group if (playerGroup != null) { foreach (GamePlayer p in playerGroup) { if (p.HealthPercent < GS.ServerProperties.Properties.NPC_HEAL_THRESHOLD && !spell.TargetHasEffect(p) && GameMath.IsWithinRadius(Body, p, spell.Range)) { Body.TargetObject = p; break; } } } break; #endregion default: log.Warn($"CheckDefensiveSpells() encountered an unknown spell type [{spell.SpellType}], calling base method"); return(base.CheckDefensiveSpells(spell)); } if (Body.TargetObject != null) { casted = Body.CastSpell(spell, m_mobSpellLine); if (casted && spell.CastTime > 0) { if (Body.IsMoving) { Body.StopFollowing(); } if (Body.TargetObject != Body) { Body.TurnTo(Body.TargetObject); } } } Body.TargetObject = lastTarget; return(casted); }
private void TrySpawnGroupAt(BlockPos origin, Vec3d posAsVec, EntityProperties entityType, EntityProperties[] grouptypes) { BlockPos pos = origin.Copy(); float xRel = (float)(posAsVec.X % chunksize) / chunksize; float zRel = (float)(posAsVec.Z % chunksize) / chunksize; int climate = GameMath.BiLerpRgbColor(xRel, zRel, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); float temp = TerraGenConfig.GetScaledAdjustedTemperatureFloat((climate >> 16) & 0xff, (int)posAsVec.Y - TerraGenConfig.seaLevel); float rain = ((climate >> 8) & 0xff) / 255f; float forestDensity = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, xRel, zRel); float shrubDensity = GameMath.BiLerp(shrubsUpLeft, shrubsUpRight, shrubsBotLeft, shrubsBotRight, xRel, zRel); int spawned = 0; WorldGenSpawnConditions sc = entityType.Server.SpawnConditions.Worldgen; bool hasCompanions = sc.Companions != null && sc.Companions.Length > 0; spawnPositions.Clear(); int nextGroupSize = 0; int tries = 10; while (nextGroupSize <= 0 && tries-- > 0) { float val = sc.GroupSize.nextFloat(); nextGroupSize = (int)val + ((val - (int)val) > rnd.NextDouble() ? 1 : 0); } for (int i = 0; i < nextGroupSize * 4 + 5; i++) { if (spawned >= nextGroupSize) { break; } EntityProperties typeToSpawn = entityType; // First entity 80% chance to spawn the dominant creature, every subsequent only 20% chance for males (or even lower if more than 5 companion types) double dominantChance = i == 0 ? 0.8 : Math.Min(0.2, 1f / grouptypes.Length); if (grouptypes.Length > 1 && rnd.NextDouble() > dominantChance) { typeToSpawn = grouptypes[1 + rnd.Next(grouptypes.Length - 1)]; } posAsVec.Set(pos.X + 0.5, pos.Y + 0.005, pos.Z + 0.5); IBlockAccessor blockAccesssor = wgenBlockAccessor.GetChunkAtBlockPos(pos.X, pos.Y, pos.Z) == null ? api.World.BlockAccessor : wgenBlockAccessor; IMapChunk mapchunk = blockAccesssor.GetMapChunkAtBlockPos(pos); if (mapchunk != null) { ushort[] heightMap = mapchunk.WorldGenTerrainHeightMap; pos.Y = sc.TryOnlySurface ? heightMap[((int)pos.Z % chunksize) * chunksize + ((int)pos.X % chunksize)] + 1 : pos.Y ; xRel = (float)(posAsVec.X % chunksize) / chunksize; zRel = (float)(posAsVec.Z % chunksize) / chunksize; climate = GameMath.BiLerpRgbColor(xRel, zRel, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); temp = TerraGenConfig.GetScaledAdjustedTemperatureFloat((climate >> 16) & 0xff, (int)posAsVec.Y - TerraGenConfig.seaLevel); rain = ((climate >> 8) & 0xff) / 255f; forestDensity = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, xRel, zRel) / 255f; shrubDensity = GameMath.BiLerp(shrubsUpLeft, shrubsUpRight, shrubsBotLeft, shrubsBotRight, xRel, zRel) / 255f; if (CanSpawnAt(blockAccesssor, typeToSpawn, pos, posAsVec, sc, rain, temp, forestDensity, shrubDensity)) { spawnPositions.Add(new SpawnOppurtunity() { ForType = typeToSpawn, Pos = posAsVec.Clone() }); spawned++; } } pos.X = origin.X + ((rnd.Next(11) - 5) + (rnd.Next(11) - 5)) / 2; pos.Z = origin.Z + ((rnd.Next(11) - 5) + (rnd.Next(11) - 5)) / 2; } // Only spawn if the group reached the minimum group size if (spawnPositions.Count >= nextGroupSize) { long herdId = api.WorldManager.GetNextHerdId(); foreach (SpawnOppurtunity so in spawnPositions) { Entity ent = CreateEntity(so.ForType, so.Pos); if (ent is EntityAgent) { (ent as EntityAgent).HerdId = herdId; } if (wgenBlockAccessor.GetChunkAtBlockPos(pos.X, pos.Y, pos.Z) == null) { api.World.SpawnEntity(ent); } else { wgenBlockAccessor.AddEntity(ent); } } //Console.WriteLine("Spawn a group of {0}x{1} at {2}", spawnPositions.Count, entityType.Code, origin); } }
// Requirements: // - ✔ Try to not move a lot vertically // - ✔ If territorial: Stay close to the spawn point // - ✔ If air habitat: Don't go above maxHeight blocks above surface // - ✔ If land habitat: Don't walk into water, prefer surface // - ~~If cave habitat: Prefer caves~~ // - ✔ If water habitat: Don't walk onto land // - ✔ Try not to fall from very large heights. Try not to fall from any large heights if entity has FallDamage // - ✔ Prefer preferredLightLevel // - ✔ If land habitat: Must be above a block the entity can stand on // - ✔ if failed searches is high, reduce wander range public Vec3d loadNextWanderTarget() { EnumHabitat habitat = entity.Properties.Habitat; bool canFallDamage = entity.Properties.FallDamage; bool territorial = StayCloseToSpawn; int tries = 9; Vec4d bestTarget = null; Vec4d curTarget = new Vec4d(); BlockPos tmpPos = new BlockPos(); if (FailedConsecutivePathfinds > 10) { WanderRangeMul = Math.Max(0.1f, WanderRangeMul * 0.9f); } else { WanderRangeMul = Math.Min(1, WanderRangeMul * 1.1f); if (rand.NextDouble() < 0.05) { WanderRangeMul = Math.Min(1, WanderRangeMul * 1.5f); } } float wRangeMul = WanderRangeMul; double dx, dy, dz; if (rand.NextDouble() < 0.05) { wRangeMul *= 3; } while (tries-- > 0) { dx = wanderRangeHorizontal.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul; dy = wanderRangeVertical.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul; dz = wanderRangeHorizontal.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul; curTarget.X = entity.ServerPos.X + dx; curTarget.Y = entity.ServerPos.Y + dy; curTarget.Z = entity.ServerPos.Z + dz; curTarget.W = 1; if (StayCloseToSpawn) { double distToEdge = curTarget.SquareDistanceTo(SpawnPosition) / (MaxDistanceToSpawn * MaxDistanceToSpawn); // Prefer staying close to spawn curTarget.W = 1 - distToEdge; } Block waterorIceBlock; switch (habitat) { case EnumHabitat.Air: int rainMapY = world.BlockAccessor.GetRainMapHeightAt((int)curTarget.X, (int)curTarget.Z); // Don't fly above max height curTarget.Y = Math.Min(curTarget.Y, rainMapY + maxHeight); // Cannot be in water waterorIceBlock = entity.World.BlockAccessor.GetLiquidBlock((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z); if (waterorIceBlock.IsLiquid()) { curTarget.W = 0; } break; case EnumHabitat.Land: curTarget.Y = moveDownToFloor((int)curTarget.X, curTarget.Y, (int)curTarget.Z); // No floor found if (curTarget.Y < 0) { curTarget.W = 0; } else { // Does not like water waterorIceBlock = entity.World.BlockAccessor.GetLiquidBlock((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z); if (waterorIceBlock.IsLiquid()) { curTarget.W /= 2; } // Lets make a straight line plot to see if we would fall off a cliff bool stop = false; bool willFall = false; float angleHor = (float)Math.Atan2(dx, dz) + GameMath.PIHALF; Vec3d target1BlockAhead = curTarget.XYZ.Ahead(1, 0, angleHor); Vec3d startAhead = entity.ServerPos.XYZ.Ahead(1, 0, angleHor); // Otherwise they are forever stuck if they stand over the edge int prevY = (int)startAhead.Y; GameMath.BresenHamPlotLine2d((int)startAhead.X, (int)startAhead.Z, (int)target1BlockAhead.X, (int)target1BlockAhead.Z, (x, z) => { if (stop) { return; } double nowY = moveDownToFloor(x, prevY, z); // Not more than 4 blocks down if (nowY < 0 || prevY - nowY > 4) { willFall = true; stop = true; } // Not more than 2 blocks up if (nowY - prevY > 2) { stop = true; } prevY = (int)nowY; }); if (willFall) { curTarget.W = 0; } } break; case EnumHabitat.Sea: waterorIceBlock = entity.World.BlockAccessor.GetLiquidBlock((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z); if (!waterorIceBlock.IsLiquid()) { curTarget.W = 0; } break; case EnumHabitat.Underwater: waterorIceBlock = entity.World.BlockAccessor.GetLiquidBlock((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z); if (!waterorIceBlock.IsLiquid()) { curTarget.W = 0; } else { curTarget.W = 1 / (Math.Abs(dy) + 1); //prefer not too much vertical change when underwater } //TODO: reject (or de-weight) targets not in direct line of sight (avoiding terrain) break; } if (curTarget.W > 0) { // Try to not hug the wall so much for (int i = 0; i < BlockFacing.HORIZONTALS.Length; i++) { BlockFacing face = BlockFacing.HORIZONTALS[i]; if (entity.World.BlockAccessor.IsSideSolid((int)curTarget.X + face.Normali.X, (int)curTarget.Y, (int)curTarget.Z + face.Normali.Z, face.Opposite)) { curTarget.W *= 0.5; } } } if (preferredLightLevel != null && curTarget.W != 0) { tmpPos.Set((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z); int lightdiff = Math.Abs((int)preferredLightLevel - entity.World.BlockAccessor.GetLightLevel(tmpPos, EnumLightLevelType.MaxLight)); curTarget.W /= Math.Max(1, lightdiff); } if (bestTarget == null || curTarget.W > bestTarget.W) { bestTarget = new Vec4d(curTarget.X, curTarget.Y, curTarget.Z, curTarget.W); if (curTarget.W >= 1.0) { break; //have a good enough target, no need for further tries } } } if (bestTarget.W > 0) { //double bla = bestTarget.Y; //bestTarget.Y += 1; //dx = bestTarget.X - entity.ServerPos.X; //dz = bestTarget.Z - entity.ServerPos.Z; //Vec3d sadf = bestTarget.XYZ.Ahead(1, 0, (float)Math.Atan2(dx, dz) + GameMath.PIHALF); /*(entity.Api as ICoreServerAPI).World.HighlightBlocks(world.AllOnlinePlayers[0], 10, new List<BlockPos>() { * new BlockPos((int)bestTarget.X, (int)bestTarget.Y, (int)bestTarget.Z) }, new List<int>() { ColorUtil.ColorFromRgba(0, 255, 0, 80) }, EnumHighlightBlocksMode.Absolute, EnumHighlightShape.Arbitrary); * (entity.Api as ICoreServerAPI).World.HighlightBlocks(world.AllOnlinePlayers[0], 11, new List<BlockPos>() { * new BlockPos((int)sadf.X, (int)sadf.Y, (int)sadf.Z) }, new List<int>() { ColorUtil.ColorFromRgba(0, 255, 255, 180) }, EnumHighlightBlocksMode.Absolute, EnumHighlightShape.Arbitrary);*/ //bestTarget.Y = bla; FailedConsecutivePathfinds = Math.Max(FailedConsecutivePathfinds - 3, 0); return(bestTarget.XYZ); } FailedConsecutivePathfinds++; return(null); }
public override void DoRender3DOpaque(float dt, bool isShadowPass) { IRenderAPI rapi = capi.Render; // the value 22 is just trial&error, should probably be something proportial to the // 13ms game ticks (which is the physics frame rate) lerpedPos.X += (entity.Pos.X - lerpedPos.X) * 22 * dt; lerpedPos.Y += (entity.Pos.Y - lerpedPos.Y) * 22 * dt; lerpedPos.Z += (entity.Pos.Z - lerpedPos.Z) * 22 * dt; ItemRenderInfo renderInfo = rapi.GetItemStackRenderInfo(inslot, EnumItemRenderTarget.Ground); if (renderInfo.ModelRef == null) { return; } inslot.Itemstack.Collectible.OnBeforeRender(capi, inslot.Itemstack, EnumItemRenderTarget.Ground, ref renderInfo); IStandardShaderProgram prog = null; LoadModelMatrix(renderInfo, isShadowPass, dt); if (isShadowPass) { rapi.CurrentActiveShader.BindTexture2D("tex2d", renderInfo.TextureId, 0); float[] mvpMat = Mat4f.Mul(ModelMat, capi.Render.CurrentModelviewMatrix, ModelMat); Mat4f.Mul(mvpMat, capi.Render.CurrentProjectionMatrix, mvpMat); capi.Render.CurrentActiveShader.UniformMatrix("mvpMatrix", mvpMat); capi.Render.CurrentActiveShader.Uniform("origin", new Vec3f()); } else { prog = rapi.StandardShader; prog.Use(); prog.Tex2D = renderInfo.TextureId; prog.RgbaTint = ColorUtil.WhiteArgbVec; prog.DontWarpVertices = 0; prog.NormalShaded = 1; prog.AlphaTest = renderInfo.AlphaTest; if (entity.Swimming) { prog.AddRenderFlags = (entityitem.Itemstack.Collectible.MaterialDensity > 1000 ? 0 : 1) << 12; prog.WaterWaveCounter = capi.Render.ShaderUniforms.WaterWaveCounter; } else { prog.AddRenderFlags = 0; } prog.OverlayOpacity = renderInfo.OverlayOpacity; if (renderInfo.OverlayTexture != null && renderInfo.OverlayOpacity > 0) { prog.Tex2dOverlay2D = renderInfo.OverlayTexture.TextureId; prog.OverlayTextureSize = new Vec2f(renderInfo.OverlayTexture.Width, renderInfo.OverlayTexture.Height); prog.BaseTextureSize = new Vec2f(renderInfo.TextureSize.Width, renderInfo.TextureSize.Height); TextureAtlasPosition texPos = rapi.GetTextureAtlasPosition(entityitem.Itemstack); prog.BaseUvOrigin = new Vec2f(texPos.x1, texPos.y1); } BlockPos pos = entityitem.Pos.AsBlockPos; Vec4f lightrgbs = capi.World.BlockAccessor.GetLightRGBs(pos.X, pos.Y, pos.Z); int temp = (int)entityitem.Itemstack.Collectible.GetTemperature(capi.World, entityitem.Itemstack); float[] glowColor = ColorUtil.GetIncandescenceColorAsColor4f(temp); int extraGlow = GameMath.Clamp((temp - 550) / 2, 0, 255); glowRgb.R = glowColor[0]; glowRgb.G = glowColor[1]; glowRgb.B = glowColor[2]; glowRgb.A = extraGlow / 255f; prog.ExtraGlow = extraGlow; prog.RgbaAmbientIn = rapi.AmbientColor; prog.RgbaLightIn = lightrgbs; prog.RgbaGlowIn = glowRgb; prog.RgbaFogIn = rapi.FogColor; prog.FogMinIn = rapi.FogMin; prog.FogDensityIn = rapi.FogDensity; prog.ExtraGodray = 0; prog.NormalShaded = renderInfo.NormalShaded ? 1 : 0; prog.ProjectionMatrix = rapi.CurrentProjectionMatrix; prog.ViewMatrix = rapi.CameraMatrixOriginf; prog.ModelMatrix = ModelMat; ItemStack stack = entityitem.Itemstack; AdvancedParticleProperties[] ParticleProperties = stack.Block?.ParticleProperties; if (stack.Block != null && !capi.IsGamePaused) { Mat4f.MulWithVec4(ModelMat, new Vec4f(stack.Block.TopMiddlePos.X, stack.Block.TopMiddlePos.Y - 0.4f, stack.Block.TopMiddlePos.Z - 0.5f, 0), particleOutTransform); // No idea why the -0.5f and -0.4f accum += dt; if (ParticleProperties != null && ParticleProperties.Length > 0 && accum > 0.025f) { accum = accum % 0.025f; for (int i = 0; i < ParticleProperties.Length; i++) { AdvancedParticleProperties bps = ParticleProperties[i]; bps.basePos.X = particleOutTransform.X + entity.Pos.X; bps.basePos.Y = particleOutTransform.Y + entity.Pos.Y; bps.basePos.Z = particleOutTransform.Z + entity.Pos.Z; entityitem.World.SpawnParticles(bps); } } } } if (!renderInfo.CullFaces) { rapi.GlDisableCullFace(); } rapi.RenderMesh(renderInfo.ModelRef); if (!renderInfo.CullFaces) { rapi.GlEnableCullFace(); } if (!isShadowPass) { prog.Stop(); } }
void genShrubs(int chunkX, int chunkZ) { int triesShrubs = (int)treeSupplier.treeGenProps.shrubsPerChunk.nextFloat(); int dx, dz, x, z; Block block; while (triesShrubs > 0) { triesShrubs--; dx = rnd.NextInt(chunksize); dz = rnd.NextInt(chunksize); x = dx + chunkX * chunksize; z = dz + chunkZ * chunksize; int y = heightmap[dz * chunksize + dx]; if (y <= 0 || y >= worldheight - 15) { continue; } tmpPos.Set(x, y, z); block = blockAccessor.GetBlock(tmpPos); if (block.Fertility == 0) { continue; } // Place according to forest value int climate = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); float shrubChance = GameMath.BiLerp(shrubUpLeft, shrubUpRight, shrubBotLeft, shrubBotRight, (float)dx / chunksize, (float)dz / chunksize); shrubChance = GameMath.Clamp(shrubChance + 255 * forestMod, 0, 255); if (rnd.NextDouble() > (shrubChance / 255f) * (shrubChance / 255f)) { continue; } TreeGenForClimate treegenParams = treeSupplier.GetRandomShrubGenForClimate(climate, (int)shrubChance, y); if (treegenParams != null) { bool canGen = true; for (int i = 0; i < structuresIntersectingChunk.Count; i++) { if (structuresIntersectingChunk[i].Contains(tmpPos)) { canGen = false; break; } } if (!canGen) { continue; } if (blockAccessor.GetBlock(tmpPos.X, tmpPos.Y, tmpPos.Z).Replaceable >= 6000) { tmpPos.Y--; } treegenParams.treeGen.GrowTree( blockAccessor, tmpPos, true, treegenParams.size, treegenParams.vinesGrowthChance ); } } }
public override void Initialize(EntityProperties properties, JsonObject attributes) { base.Initialize(properties, attributes); skintree = entity.WatchedAttributes.GetTreeAttribute("skinConfig"); if (skintree == null) { entity.WatchedAttributes["skinConfig"] = skintree = new TreeAttribute(); } entity.WatchedAttributes.RegisterModifiedListener("skinConfig", onSkinConfigChanged); entity.WatchedAttributes.RegisterModifiedListener("voicetype", onVoiceConfigChanged); entity.WatchedAttributes.RegisterModifiedListener("voicepitch", onVoiceConfigChanged); AvailableSkinParts = properties.Attributes["skinnableParts"].AsObject <SkinnablePart[]>(); foreach (var val in AvailableSkinParts) { string partCode = val.Code; val.VariantsByCode = new Dictionary <string, SkinnablePartVariant>(); AvailableSkinPartsByCode[val.Code] = val; if (val.Type == EnumSkinnableType.Texture && entity.Api.Side == EnumAppSide.Client) { ICoreClientAPI capi = entity.Api as ICoreClientAPI; LoadedTexture texture = new LoadedTexture(capi); foreach (var variant in val.Variants) { AssetLocation textureLoc; if (val.TextureTemplate != null) { textureLoc = val.TextureTemplate.Clone(); textureLoc.Path = textureLoc.Path.Replace("{code}", variant.Code); } else { textureLoc = variant.Texture; } IAsset asset = capi.Assets.TryGet(textureLoc.Clone().WithPathAppendixOnce(".png").WithPathPrefixOnce("textures/"), true); int r = 0, g = 0, b = 0; float c = 0; BitmapRef bmp = asset.ToBitmap(capi); for (int i = 0; i < 8; i++) { Vec2d vec = GameMath.R2Sequence2D(i); Color col2 = bmp.GetPixelRel((float)vec.X, (float)vec.Y); if (col2.A > 0.5) { r += col2.R; g += col2.G; b += col2.B; c++; } } bmp.Dispose(); c = Math.Max(1, c); variant.Color = ColorUtil.ColorFromRgba((int)(r / c), (int)(g / c), (int)(b / c), 255); val.VariantsByCode[variant.Code] = variant; } } else { foreach (var variant in val.Variants) { val.VariantsByCode[variant.Code] = variant; } } } if (entity.Api.Side == EnumAppSide.Server && AppliedSkinParts.Count == 0) { foreach (var val in AvailableSkinParts) { string partCode = val.Code; string variantCode = val.Variants[entity.World.Rand.Next(val.Variants.Length)].Code; selectSkinPart(partCode, variantCode, false); } } onVoiceConfigChanged(); }
/// <summary> /// Do we continue playing this track? /// </summary> /// <param name="dt">Delta time or Change in time</param> /// <param name="props">The properties of the current track.</param> /// <returns>Are we still playing or do we stop?</returns> public bool ContinuePlay(float dt, TrackedPlayerProperties props) { if (props.sunSlight > 3 || !ShouldPlayCaveMusic) { FadeOut(3); return(false); } if (activeUntilMs > 0 && capi.World.ElapsedMilliseconds >= activeUntilMs) { // Ok, time to stop. We play the current tracks until the end and stop bool active = IsActive; if (!active) { activeUntilMs = 0; foreach (MusicTrackPart part in Parts) { part.Sound?.Dispose(); } } return(active); } int quantityActive = 0; for (int i = 0; i < Parts.Length; i++) { quantityActive += (Parts[i].IsPlaying || Parts[i].Loading) ? 1: 0; } int beforePlaying = quantityActive; GameMath.Shuffle(rand, PartsShuffled); for (int i = 0; i < PartsShuffled.Length; i++) { MusicTrackPart part = PartsShuffled[i]; if (part.Files.Length == 0) { continue; } bool isPlaying = part.IsPlaying; bool shouldPlay = part.Applicable(capi.World, props); // Part has recently ended if (!isPlaying && part.Sound != null) { part.Sound.Dispose(); part.Sound = null; continue; } // Part should be stopped if (isPlaying && !shouldPlay) { if (!part.Sound.IsFadingOut) { part.Sound.FadeOut(3, (sound) => { part.Sound.Dispose(); part.Sound = null; }); } continue; } bool shouldStart = !isPlaying && shouldPlay && !part.Loading && quantityActive < maxSimultaenousTracks && (quantityActive == 0 || rand.NextDouble() < simultaenousTrackChance) ; if (shouldStart) { AssetLocation location = part.Files[rand.Next(part.Files.Length)]; part.NowPlayingFile = location; part.Loading = true; musicEngine.LoadTrack(location, (sound) => { if (sound != null) { sound.Start(); part.Sound = sound; } part.Loading = false; }); part.StartedMs = capi.World.ElapsedMilliseconds; quantityActive++; } } return(true); }
private void OnScanComplete() { quantityNearbyFlowers = scanQuantityNearbyFlowers; quantityNearbyHives = scanQuantityNearbyHives; emptySkeps = new List <BlockPos>(scanEmptySkeps); if (emptySkeps.Count == 0) { skepToPop = null; } hivePopSize = (EnumHivePopSize)GameMath.Clamp(quantityNearbyFlowers - 3 * quantityNearbyHives, 0, 2); MarkDirty(); if (3 * quantityNearbyHives + 3 > quantityNearbyFlowers) { skepToPop = null; MarkDirty(false); return; } if (skepToPop != null && api.World.Calendar.TotalHours > beginPopStartTotalHours + popHiveAfterHours) { TryPopCurrentSkep(); cooldownUntilTotalHours = api.World.Calendar.TotalHours + 4 * 24; MarkDirty(false); return; } // Default Spread speed: Once every 4 in game days * factor // Don't spread at all if 3 * livinghives + 3 > flowers // factor = Clamped(livinghives / Math.Sqrt(flowers - 3 * livinghives - 3), 1, 1000) // After spreading: 4 extra days cooldown if (skepToPop != null) { float newPopHours = 4 * 24 * GameMath.Clamp(quantityNearbyHives / GameMath.Sqrt(quantityNearbyFlowers - 3 * quantityNearbyHives - 3), 1, 1000); this.popHiveAfterHours = (float)(0.75 * popHiveAfterHours + 0.25 * newPopHours); if (!emptySkeps.Contains(skepToPop)) { skepToPop = null; MarkDirty(false); return; } } else { popHiveAfterHours = 4 * 24 * GameMath.Clamp(quantityNearbyHives / GameMath.Sqrt(quantityNearbyFlowers - 3 * quantityNearbyHives - 3), 1, 1000); beginPopStartTotalHours = api.World.Calendar.TotalHours; float mindistance = 999; BlockPos closestPos = new BlockPos(); foreach (BlockPos pos in emptySkeps) { float dist = pos.DistanceTo(this.pos); if (dist < mindistance) { mindistance = dist; closestPos = pos; } } skepToPop = closestPos; } }
public override void OnGameTick(float deltaTime) { if (!enabled) { return; } if (requireInitSounds) { initSoundsAndEffects(); requireInitSounds = false; } if (entity.World.Side == EnumAppSide.Client) { if (!(entity.World.Api as ICoreClientAPI).PlayerReadyFired) { return; } } else { IServerPlayer player = entity.World.PlayerByUid(((EntityPlayer)entity).PlayerUID) as IServerPlayer; if (player != null && player.ConnectionState != EnumClientState.Playing) { return; } } deltaTime = GameMath.Min(0.5f, deltaTime); float changeSpeed = deltaTime / 3; double hereStability = stabilityOffset + tempStabilitySystem.GetTemporalStability(entity.SidedPos.X, entity.SidedPos.Y, entity.SidedPos.Z); entity.Attributes.SetDouble("tempStabChangeVelocity", TempStabChangeVelocity); double gain = TempStabChangeVelocity > 0 ? (TempStabChangeVelocity / 200.0) : (TempStabChangeVelocity / 800.0); OwnStability = GameMath.Clamp(OwnStability + gain, 0f, 1); double ownStability = OwnStability; TempStabChangeVelocity = (hereTempStabChangeVelocity - TempStabChangeVelocity) * deltaTime; float glitchEffectExtraStrength = tempStabilitySystem.GetGlitchEffectExtraStrength(); double targetGlitchEffectStrength = Math.Max(0, Math.Max(0, (0.2f - ownStability) * 1 / 0.2f) + glitchEffectExtraStrength); glitchEffectStrength += (targetGlitchEffectStrength - glitchEffectStrength) * changeSpeed; glitchEffectStrength = GameMath.Clamp(glitchEffectStrength, 0, 1.1f); double targetFogEffectStrength = Math.Max(0, Math.Max(0, (0.3f - ownStability) * 1 / 0.3f) + glitchEffectExtraStrength); fogEffectStrength += (targetFogEffectStrength - fogEffectStrength) * changeSpeed; fogEffectStrength = GameMath.Clamp(fogEffectStrength, 0, 1.1f); double targetRustPrecipStrength = Math.Max(0, Math.Max(0, (0.3f - ownStability) * 1 / 0.3f) + glitchEffectExtraStrength); rustPrecipColorStrength += (targetRustPrecipStrength - rustPrecipColorStrength) * changeSpeed; rustPrecipColorStrength = GameMath.Clamp(rustPrecipColorStrength, 0, 1f); if (precipParticleSys != null) { precipParticleSys.rainParticleColor = ColorUtil.ColorOverlay(WeatherSimulationParticles.waterColor, WeatherSimulationParticles.lowStabColor, (float)rustPrecipColorStrength); } hereTempStabChangeVelocity = hereStability - 1; oneSecAccum += deltaTime; if (oneSecAccum > 1) { oneSecAccum = 0; updateSoundsAndEffects(hereStability, Math.Max(0, ownStability - 1.5f * glitchEffectExtraStrength)); } threeSecAccum += deltaTime; if (threeSecAccum > 4) { threeSecAccum = 0; if (entity.World.Side == EnumAppSide.Server && ownStability < 0.13) { entity.ReceiveDamage(new DamageSource() { DamageTier = 0, Source = EnumDamageSource.Machine, Type = EnumDamageType.Poison }, (float)(0.15 - ownStability)); } } if (isSelf) { capi.Render.ShaderUniforms.GlitchStrength = 0; } if (isSelf && (fogEffectStrength > 0.05 || glitchEffectStrength > 0.05)) { capi.Render.ShaderUniforms.GlitchStrength = (float)glitchEffectStrength; capi.Render.ShaderUniforms.GlobalWorldWarp = (float)(capi.World.Rand.NextDouble() < 0.015 ? (Math.Max(0, glitchEffectStrength - 0.05f) * capi.World.Rand.NextDouble() * capi.World.Rand.NextDouble()) : 0); capi.Render.ShaderUniforms.WindWaveCounter += (float)(capi.World.Rand.NextDouble() < 0.015 ? 9 * capi.World.Rand.NextDouble() : 0); capi.Render.ShaderUniforms.WaterWaveCounter += (float)(capi.World.Rand.NextDouble() < 0.015 ? 9 * capi.World.Rand.NextDouble() : 0); if (capi.World.Rand.NextDouble() < 0.002) { capi.Input.MouseYaw += (float)capi.World.Rand.NextDouble() * 0.125f - 0.125f / 2; capi.Input.MousePitch += (float)capi.World.Rand.NextDouble() * 0.125f - 0.125f / 2; } tmpPos.Set((int)entity.Pos.X, (int)entity.Pos.Y, (int)entity.Pos.Z); float sunb = capi.World.BlockAccessor.GetLightLevel(tmpPos, EnumLightLevelType.OnlySunLight) / 22f; float strength = Math.Min(1, (float)(glitchEffectStrength)); double fognoise = fogEffectStrength * Math.Abs(fogNoise.Noise(0, capi.InWorldEllapsedMilliseconds / 1000f)) / 60f; rainfogAmbient.FogDensity.Value = 0.05f + (float)fognoise; rainfogAmbient.AmbientColor.Weight = strength; rainfogAmbient.FogColor.Weight = strength; rainfogAmbient.FogDensity.Weight = (float)Math.Pow(strength, 2); rainfogAmbient.FogColor.Value[0] = sunb * 116 / 255f; rainfogAmbient.FogColor.Value[1] = sunb * 77 / 255f; rainfogAmbient.FogColor.Value[2] = sunb * 49 / 255f; rainfogAmbient.AmbientColor.Value[0] = 0.5f * 116 / 255f; rainfogAmbient.AmbientColor.Value[1] = 0.5f * 77 / 255f; rainfogAmbient.AmbientColor.Value[2] = 0.5f * 49 / 255f; rustParticles.MinVelocity.Set(-0.1f, 0.1f, 0.1f); rustParticles.AddVelocity.Set(0.2f, 0.2f, 0.2f); rustParticles.Color = ColorUtil.ToRgba((int)(strength * 150), 50, 25, 15); rustParticles.MaxSize = 0.25f; rustParticles.RandomVelocityChange = false; rustParticles.MinVelocity.Set(0, 0, 0); rustParticles.AddVelocity.Set(0, 1, 0); Vec3d position = new Vec3d(); EntityPos plrPos = capi.World.Player.Entity.Pos; float tries = 20 * strength; while (tries-- > 0) { float offX = (float)capi.World.Rand.NextDouble() * 24 - 12; float offY = (float)capi.World.Rand.NextDouble() * 24 - 12; float offZ = (float)capi.World.Rand.NextDouble() * 24 - 12; position.Set(plrPos.X + offX, plrPos.Y + offY, plrPos.Z + offZ); BlockPos pos = new BlockPos((int)position.X, (int)position.Y, (int)position.Z); if (!capi.World.BlockAccessor.IsValidPos(pos)) { continue; } rustParticles.MinPos = position; capi.World.SpawnParticles(rustParticles); } } }
public void tick() { while (enable) { bool intersect_x_r = false, intersect_x_l = false, intersect_y_t = false, intersect_y_b = false; for (int i = 0; i < list.Count - 1; i++) { Car car1 = list[i]; PointF[] colliderBuffer = GameMath.copyPointArray(car1.collider); for (int x = 0; x < colliderBuffer.Length; x++) { colliderBuffer[x].X = colliderBuffer[x].X * car1.scale.x; colliderBuffer[x].Y = colliderBuffer[x].Y * car1.scale.y; } for (int j = i + 1; j < list.Count; j++) { Car car2 = list[j]; PointF[] colliderBuffer2 = GameMath.rotate(car2.collider, car2.rotate - car1.rotate); Vector2f r = GameMath.rotate(car2.position - car1.position, -car1.rotate); for (int x = 0; x < colliderBuffer2.Length; x++) { colliderBuffer2[x].X = (colliderBuffer2[x].X) * car2.scale.x + r.x; colliderBuffer2[x].Y = (colliderBuffer2[x].Y) * car2.scale.y + r.y; } intersect_x_r = false; intersect_x_l = false; intersect_y_t = false; intersect_y_b = false; for (int c1 = 0; c1 < colliderBuffer.Length; c1++) { for (int c2 = 0; c2 < colliderBuffer2.Length; c2++) { if (colliderBuffer[c1].X >= colliderBuffer2[c2].X) { intersect_x_l = true; } else if (colliderBuffer[c1].X <= colliderBuffer2[c2].X) { intersect_x_r = true; } if (colliderBuffer[c1].Y >= colliderBuffer2[c2].Y) { intersect_y_b = true; } else if (colliderBuffer[c1].Y <= colliderBuffer2[c2].Y) { intersect_y_t = true; } if (intersect_x_r && intersect_x_l && intersect_y_b && intersect_y_t) { c1 = colliderBuffer.Length; break; } } } if (intersect_x_r && intersect_x_l && intersect_y_b && intersect_y_t) { if (car1.acceleration.x > 0) { if (car1.position.x > car2.position.x) { car2.collide(CAR_COLLIDE); } else { car1.collide(CAR_COLLIDE); } } else if (car1.acceleration.x < 0) { if (car1.position.x < car2.position.x) { car2.collide(CAR_COLLIDE); } else { car1.collide(CAR_COLLIDE); } } else if (car1.acceleration.y > 0) { if (car1.position.y > car2.position.y) { car2.collide(CAR_COLLIDE); } else { car1.collide(CAR_COLLIDE); } // } else if (car1.acceleration.y < 0) { if (car1.position.y < car2.position.y) { car2.collide(CAR_COLLIDE); } else { car1.collide(CAR_COLLIDE); } } } } } for (int i = 0; i < list.Count; i++) { Car car = list[i]; PointF[] colliderBuffer = GameMath.rotate(car.collider, car.rotate); for (int x = 0; x < colliderBuffer.Length; x++) { colliderBuffer[x].X = colliderBuffer[x].X * car.scale.x + car.position.x; colliderBuffer[x].Y = colliderBuffer[x].Y * car.scale.y + car.position.y; } intersect_x_r = false; intersect_x_l = false; intersect_y_t = false; intersect_y_b = false; for (int c1 = 0; c1 < colliderBuffer.Length; c1++) { for (int c2 = 0; c2 < trafficLightZone.Length; c2++) { if (colliderBuffer[c1].X >= trafficLightZone[c2].X) { intersect_x_l = true; } else if (colliderBuffer[c1].X <= trafficLightZone[c2].X) { intersect_x_r = true; } if (colliderBuffer[c1].Y >= trafficLightZone[c2].Y) { intersect_y_b = true; } else if (colliderBuffer[c1].Y <= trafficLightZone[c2].Y) { intersect_y_t = true; } if (intersect_x_r && intersect_x_l && intersect_y_b && intersect_y_t) { c1 = colliderBuffer.Length; break; } } } if (intersect_x_r && intersect_x_l && intersect_y_b && intersect_y_t) { if (car.maxSpeed.x != 0 && horizont == false && !car.collideTrafficZone) { car.collide(TRAFFIC_LIGHT_COLLIDE); } else if (car.maxSpeed.y != 0 && vertical == false && !car.collideTrafficZone) { car.collide(TRAFFIC_LIGHT_COLLIDE); } else { car.collideTrafficZone = true; } } else if (car.collideTrafficZone) { car.collideTrafficZone = false; } } } }
protected BlockSchematicStructure GetGeneratableStructure(VillageSchematic schem, IBlockAccessor blockAccessor, IWorldAccessor worldForCollectibleResolve, BlockPos pos) { int chunksize = blockAccessor.ChunkSize; int climate = GameMath.BiLerpRgbColor((float)(pos.X % chunksize) / chunksize, (float)(pos.Z % chunksize) / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); int num = rand.NextInt(schem.Structures.Length); BlockSchematicStructure schematic = schem.Structures[num]; int widthHalf = (int)Math.Ceiling(schematic.SizeX / 2f); int lengthHalf = (int)Math.Ceiling(schematic.SizeZ / 2f); pos.Y += schem.OffsetY; // Probe all 4 corners + center if they are on the same height int centerY = blockAccessor.GetTerrainMapheightAt(pos); tmpPos.Set(pos.X - widthHalf, 0, pos.Z - lengthHalf); int topLeftY = blockAccessor.GetTerrainMapheightAt(tmpPos); tmpPos.Set(pos.X + widthHalf, 0, pos.Z - lengthHalf); int topRightY = blockAccessor.GetTerrainMapheightAt(tmpPos); tmpPos.Set(pos.X - widthHalf, 0, pos.Z + lengthHalf); int botLeftY = blockAccessor.GetTerrainMapheightAt(tmpPos); tmpPos.Set(pos.X + widthHalf, 0, pos.Z + lengthHalf); int botRightY = blockAccessor.GetTerrainMapheightAt(tmpPos); int diff = GameMath.Max(centerY, topLeftY, topRightY, botLeftY, botRightY) - GameMath.Min(centerY, topLeftY, topRightY, botLeftY, botRightY); if (diff > 2) { return(null); } pos.Y += centerY - pos.Y + 1 + schem.OffsetY; if (pos.Y <= 0) { return(null); } // Ensure not floating on water tmpPos.Set(pos.X - widthHalf, pos.Y - 1, pos.Z - lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X + widthHalf, pos.Y - 1, pos.Z - lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X - widthHalf, pos.Y - 1, pos.Z + lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X + widthHalf, pos.Y - 1, pos.Z + lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } // Ensure not submerged in water tmpPos.Set(pos.X - widthHalf, pos.Y, pos.Z - lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X + widthHalf, pos.Y, pos.Z - lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X - widthHalf, pos.Y, pos.Z + lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X + widthHalf, pos.Y, pos.Z + lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X - widthHalf, pos.Y + 1, pos.Z - lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X + widthHalf, pos.Y + 1, pos.Z - lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X - widthHalf, pos.Y + 1, pos.Z + lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } tmpPos.Set(pos.X + widthHalf, pos.Y + 1, pos.Z + lengthHalf); if (blockAccessor.GetBlock(tmpPos).IsLiquid()) { return(null); } if (!TestUndergroundCheckPositions(blockAccessor, pos, schematic.UndergroundCheckPositions)) { return(null); } if (isStructureAt(pos, worldForCollectibleResolve)) { return(null); } return(schematic); }
public void OnRenderFrame(float deltaTime, EnumRenderStage stage) { if (!renderAurora) { return; } if (capi.Render.FrameWidth == 0) { return; } quarterSecAccum += deltaTime; if (quarterSecAccum > 0.25f) { plrPos.X = (int)capi.World.Player.Entity.CameraPos.X; plrPos.Y = capi.World.SeaLevel; plrPos.Z = (int)capi.World.Player.Entity.CameraPos.Z; clientClimateCond = capi.World.BlockAccessor.GetClimateAt(plrPos); quarterSecAccum = 0; } if (clientClimateCond == null) { return; } float tempfac = GameMath.Clamp((Math.Max(0, -clientClimateCond.Temperature) - 5) / 15f, 0, 1); col.W = GameMath.Clamp(1 - 1.5f * capi.World.Calendar.DayLightStrength, 0, 1) * tempfac; if (col.W <= 0) { return; } prog.Use(); prog.Uniform("color", col); prog.Uniform("rgbaFogIn", capi.Ambient.BlendedFogColor); prog.Uniform("fogMinIn", capi.Ambient.BlendedFogMin); prog.Uniform("fogDensityIn", capi.Ambient.BlendedFogDensity); prog.UniformMatrix("projectionMatrix", capi.Render.CurrentProjectionMatrix); prog.Uniform("flatFogDensity", capi.Ambient.BlendedFlatFogDensity); prog.Uniform("flatFogStart", capi.Ambient.BlendedFlatFogYPosForShader); float speedmul = capi.World.Calendar.SpeedOfTime / 60f; prog.Uniform("auroraCounter", (float)(capi.InWorldEllapsedMilliseconds / 4000.0 * speedmul) % 579f); mvMat .Set(capi.Render.MvMatrix.Top) .FollowPlayer() .Translate( 0, // capi.World.BlockAccessor.MapSizeX/2, (1.1f * capi.World.BlockAccessor.MapSizeY + 0.5 - capi.World.Player.Entity.CameraPos.Y), 0 // capi.World.BlockAccessor.MapSizeZ/2 ) ; prog.UniformMatrix("modelViewMatrix", mvMat.Values); capi.Render.RenderMesh(quadTilesRef); prog.Stop(); }
public string GetKey(string holdingstack) { return(GameMath.Md5Hash(holdingstack + block.Code.ToString() + block.Id)); }
public static void Solve(List <Contact2D> contacts, int iterations, float dt) { float muD = 0.7f; bool SpecSequential = true; float dtInv = 1f / dt; for (int j = 0; j < iterations; j++) { for (int i = 0; i < contacts.Count; i++) { Contact2D con = contacts[i]; Vector2 n = con.Normal; float relNv = Vector2.Dot(con.B.Vel - con.A.Vel, n); //Do either speculative or speculative sequential if (!SpecSequential) { float remove = relNv + con.Dist * dtInv; //double remove = relNv + con.m_dist / Constants.kTimeStep(1/30); if (remove < 0) { Vector2 aVel = con.A.GetVelocityOfWorldPoint(con.pointA); Vector2 bVel = con.B.GetVelocityOfWorldPoint(con.pointB); Vector2 relVel = bVel - aVel; float mag = remove * con.InvDenom; Vector2 imp = con.Normal * mag; Vector2 t = relVel - (Vector2.Dot(relVel, n)) * n; if (!(t.Length() <= float.Epsilon)) { t = Vector2.Normalize(t); } Vector2 frictionJ = -(muD * Math.Abs(mag)) * t; con.ApplyImpulses(imp - frictionJ); } } else { Vector2 aVel = con.A.GetVelocityOfWorldPoint(con.pointA); Vector2 bVel = con.B.GetVelocityOfWorldPoint(con.pointB); Vector2 relVel = bVel - aVel; float remove = relNv + con.Dist * dtInv; float mag = remove * con.InvDenom; float newImpulse = Math.Min(mag + con.ImpulseN, 0); float change = newImpulse - con.ImpulseN; Vector2 imp = con.Normal * change; // apply impulse con.ApplyImpulses(imp); con.ImpulseN = newImpulse; float absMag = Math.Abs(con.ImpulseN) * muD; // friction mag = Vector2.Dot(relVel, GameMath.Perp2D(n)) * con.InvDenom; newImpulse = MathHelper.Clamp(mag + con.ImpulseT, -absMag, absMag); change = newImpulse - con.ImpulseT; imp = GameMath.Perp2D(n) * change; // apply impulse con.ApplyImpulses(imp); con.ImpulseT = newImpulse; } } } }
private void LoadModelMatrix(ItemRenderInfo renderInfo, bool isShadowPass, float dt) { IRenderAPI rapi = capi.Render; EntityPlayer entityPlayer = capi.World.Player.Entity; Mat4f.Identity(ModelMat); Mat4f.Translate(ModelMat, ModelMat, (float)(lerpedPos.X - entityPlayer.CameraPos.X), (float)(lerpedPos.Y - entityPlayer.CameraPos.Y), (float)(lerpedPos.Z - entityPlayer.CameraPos.Z) ); float sizeX = 0.2f * renderInfo.Transform.ScaleXYZ.X; float sizeY = 0.2f * renderInfo.Transform.ScaleXYZ.Y; float sizeZ = 0.2f * renderInfo.Transform.ScaleXYZ.Z; float dx = 0, dz = 0; if (!isShadowPass) { long ellapseMs = capi.World.ElapsedMilliseconds; bool freefall = !(entity.Collided || entity.Swimming || capi.IsGamePaused); if (!freefall) { touchGroundMS = ellapseMs; } if (entity.Collided) { xangle *= 0.55f; yangle *= 0.55f; zangle *= 0.55f; } else { float easeIn = Math.Min(1, (ellapseMs - touchGroundMS) / 200); float angleGain = freefall ? 1000 * dt / 7 * easeIn : 0; yangle += angleGain; xangle += angleGain; zangle += angleGain; } if (entity.Swimming) { float diff = 1; if (entityitem.Itemstack.Collectible.MaterialDensity > 1000) { dx = GameMath.Sin((float)(ellapseMs / 1000.0)) / 50; dz = -GameMath.Sin((float)(ellapseMs / 3000.0)) / 50; diff = 0.1f; } xangle = GameMath.Sin((float)(ellapseMs / 1000.0)) * 8 * diff; yangle = GameMath.Cos((float)(ellapseMs / 2000.0)) * 3 * diff; zangle = -GameMath.Sin((float)(ellapseMs / 3000.0)) * 8 * diff; } } Mat4f.Translate(ModelMat, ModelMat, dx + renderInfo.Transform.Translation.X, renderInfo.Transform.Translation.Y, dz + renderInfo.Transform.Translation.Z); Mat4f.Scale(ModelMat, ModelMat, new float[] { sizeX + scaleRand, sizeY + scaleRand, sizeZ + scaleRand }); Mat4f.RotateY(ModelMat, ModelMat, GameMath.DEG2RAD * (renderInfo.Transform.Rotation.Y + yangle) + (renderInfo.Transform.Rotate ? yRotRand : 0)); Mat4f.RotateZ(ModelMat, ModelMat, GameMath.DEG2RAD * (renderInfo.Transform.Rotation.Z + zangle)); Mat4f.RotateX(ModelMat, ModelMat, GameMath.DEG2RAD * (renderInfo.Transform.Rotation.X + xangle)); Mat4f.Translate(ModelMat, ModelMat, -renderInfo.Transform.Origin.X, -renderInfo.Transform.Origin.Y, -renderInfo.Transform.Origin.Z); }
public virtual bool TryPutItem(IPlayer player) { if (OwnStackSize >= MaxStackSize) { return(false); } ItemSlot hotbarSlot = player.InventoryManager.ActiveHotbarSlot; if (hotbarSlot.Itemstack == null) { return(false); } ItemSlot invSlot = inventory[0]; if (invSlot.Itemstack == null) { invSlot.Itemstack = hotbarSlot.Itemstack.Clone(); invSlot.Itemstack.StackSize = 0; Api.World.PlaySoundAt(SoundLocation, Pos.X, Pos.Y, Pos.Z, null, 0.88f + (float)Api.World.Rand.NextDouble() * 0.24f, 16); } if (invSlot.Itemstack.Equals(Api.World, hotbarSlot.Itemstack, GlobalConstants.IgnoredStackAttributes)) { bool putBulk = player.Entity.Controls.Sprint; int q = GameMath.Min(hotbarSlot.StackSize, putBulk ? BulkTakeQuantity : DefaultTakeQuantity, MaxStackSize - OwnStackSize); // add to the pile and average item temperatures int oldSize = invSlot.Itemstack.StackSize; invSlot.Itemstack.StackSize += q; if (oldSize + q > 0) { float tempPile = invSlot.Itemstack.Collectible.GetTemperature(Api.World, invSlot.Itemstack); float tempAdded = hotbarSlot.Itemstack.Collectible.GetTemperature(Api.World, hotbarSlot.Itemstack); invSlot.Itemstack.Collectible.SetTemperature(Api.World, invSlot.Itemstack, (tempPile * oldSize + tempAdded * q) / (oldSize + q), false); } if (player.WorldData.CurrentGameMode != EnumGameMode.Creative) { hotbarSlot.TakeOut(q); hotbarSlot.OnItemSlotModified(null); } Api.World.PlaySoundAt(SoundLocation, Pos.X, Pos.Y, Pos.Z, player, 0.88f + (float)Api.World.Rand.NextDouble() * 0.24f, 16); MarkDirty(); Cuboidf[] collBoxes = Api.World.BlockAccessor.GetBlock(Pos).GetCollisionBoxes(Api.World.BlockAccessor, Pos); if (collBoxes != null && collBoxes.Length > 0 && CollisionTester.AabbIntersect(collBoxes[0], Pos.X, Pos.Y, Pos.Z, player.Entity.SelectionBox, player.Entity.SidedPos.XYZ)) { player.Entity.SidedPos.Y += collBoxes[0].Y2 - (player.Entity.SidedPos.Y - (int)player.Entity.SidedPos.Y); } (player as IClientPlayer)?.TriggerFpAnimation(EnumHandInteract.HeldItemInteract); return(true); } return(false); }
void genPatches(int chunkX, int chunkZ, bool postPass) { int dx, dz, x, z; Block block; int mapsizeY = blockAccessor.MapSizeY; var mapregion = sapi?.WorldManager.GetMapRegion((chunkX * chunksize) / regionSize, (chunkZ * chunksize) / regionSize); for (int i = 0; i < bpc.PatchesNonTree.Length; i++) { BlockPatch blockPatch = bpc.PatchesNonTree[i]; if (blockPatch.PostPass != postPass) { continue; } float chance = blockPatch.Chance * bpc.ChanceMultiplier.nextFloat(); while (chance-- > rnd.NextDouble()) { dx = rnd.NextInt(chunksize); dz = rnd.NextInt(chunksize); x = dx + chunkX * chunksize; z = dz + chunkZ * chunksize; int y = heightmap[dz * chunksize + dx]; if (y <= 0 || y >= worldheight - 15) { continue; } tmpPos.Set(x, y, z); block = blockAccessor.GetBlock(tmpPos); // Place according to forest value float forestRel = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, (float)dx / chunksize, (float)dz / chunksize) / 255f; forestRel = GameMath.Clamp(forestRel + forestMod, 0, 1); float shrubRel = GameMath.BiLerp(shrubUpLeft, shrubUpRight, shrubBotLeft, shrubBotRight, (float)dx / chunksize, (float)dz / chunksize) / 255f; shrubRel = GameMath.Clamp(shrubRel + shrubMod, 0, 1); int climate = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); if (bpc.IsPatchSuitableAt(blockPatch, block, mapsizeY, climate, y, forestRel, shrubRel)) { if (blockPatch.MapCode != null && rnd.NextInt(255) > GetPatchDensity(blockPatch.MapCode, x, z, mapregion)) { continue; } int firstBlockId = 0; bool found = true; if (blockPatch.BlocksByRockType != null) { found = false; int dy = 1; while (dy < 5 && y - dy > 0) { string lastCodePart = blockAccessor.GetBlock(x, y - dy, z).LastCodePart(); if (RockBlockIdsByType.TryGetValue(lastCodePart, out firstBlockId)) { found = true; break; } dy++; } } if (found) { blockPatch.Generate(blockAccessor, rnd, x, y, z, firstBlockId); } } } } }
private static bool CanEquipItem(Item item, Skills skills) { return(item.Category != (int)ItemCategory.Resource && item.RequiredDefenseLevel <= GameMath.ExperienceToLevel(skills.Defense) && item.RequiredAttackLevel <= GameMath.ExperienceToLevel(skills.Attack)); }
void genTrees(int chunkX, int chunkZ) { int climate = GameMath.BiLerpRgbColor((float)0.5f, (float)0.5f, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); float wetrel = TerraGenConfig.GetRainFall((climate >> 8) & 0xff, heightmap[(chunksize / 2) * chunksize + chunksize / 2]) / 255f; float dryrel = 1 - wetrel; float drypenalty = 1 - GameMath.Clamp(2f * (dryrel - 0.5f), 0, 0.8f); // Reduce tree generation by up to 70% in low rain places float wetboost = 1 + 3 * Math.Max(0, wetrel - 0.75f); int triesTrees = (int)(treeSupplier.treeGenProps.treesPerChunk.nextFloat() * drypenalty * wetboost); int dx, dz, x, z; Block block; int treesGenerated = 0; while (triesTrees > 0) { triesTrees--; dx = rnd.NextInt(chunksize); dz = rnd.NextInt(chunksize); x = dx + chunkX * chunksize; z = dz + chunkZ * chunksize; int y = heightmap[dz * chunksize + dx]; if (y <= 0 || y >= worldheight - 15) { continue; } bool underwater = false; tmpPos.Set(x, y, z); block = blockAccessor.GetBlock(tmpPos); if (block.IsLiquid()) { underwater = true; tmpPos.Y--; block = blockAccessor.GetBlock(tmpPos); } if (block.IsLiquid()) { underwater = true; tmpPos.Y--; block = blockAccessor.GetBlock(tmpPos); } if (block.Fertility == 0) { continue; } // Place according to forest value float treeDensity = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, (float)dx / chunksize, (float)dz / chunksize); climate = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); treeDensity = GameMath.Clamp(treeDensity + forestMod * 255, 0, 255); float treeDensityNormalized = treeDensity / 255f; // 1 in 400 chance to always spawn a tree // otherwise go by tree density using a quadratic drop off to create clearer forest edges if (rnd.NextDouble() > Math.Max(0.0025, treeDensityNormalized * treeDensityNormalized) || forestMod <= -1) { continue; } TreeGenForClimate treegenParams = treeSupplier.GetRandomTreeGenForClimate(climate, (int)treeDensity, y, underwater); if (treegenParams != null) { bool canGen = true; for (int i = 0; i < structuresIntersectingChunk.Count; i++) { if (structuresIntersectingChunk[i].Contains(tmpPos)) { canGen = false; break; } } if (!canGen) { continue; } if (blockAccessor.GetBlock(tmpPos.X, tmpPos.Y, tmpPos.Z).Replaceable >= 6000) { tmpPos.Y--; } treegenParams.treeGen.GrowTree( blockAccessor, tmpPos, false, treegenParams.size, treegenParams.vinesGrowthChance, 1, treesGenerated ); treesGenerated++; } } }
public AddItemResult CraftItem(SessionToken token, string userId, Guid itemId) { var item = gameData.GetItem(itemId); if (item == null) { return(AddItemResult.Failed); } var character = GetCharacter(token, userId); if (character == null) { return(AddItemResult.Failed); } if (!integrityChecker.VerifyPlayer(token.SessionId, character.Id, 0)) { return(AddItemResult.Failed); } var resources = gameData.GetResources(character.ResourcesId); if (resources == null) { return(AddItemResult.Failed); } var skills = gameData.GetSkills(character.SkillsId); if (skills == null) { return(AddItemResult.Failed); } var craftingLevel = GameMath.ExperienceToLevel(skills.Crafting); if (item.WoodCost > resources.Wood || item.OreCost > resources.Ore || item.RequiredCraftingLevel > craftingLevel) { return(AddItemResult.Failed); } var craftingRequirements = gameData.GetCraftingRequirements(itemId); foreach (var req in craftingRequirements) { var invItem = gameData.GetInventoryItem(character.Id, req.ResourceItemId); if (invItem == null || invItem.Amount < req.Amount) { return(AddItemResult.Failed); } } foreach (var req in craftingRequirements) { var invItem = gameData.GetInventoryItem(character.Id, req.ResourceItemId); invItem.Amount -= req.Amount; if (invItem.Amount == 0) { gameData.Remove(invItem); } } resources.Wood -= item.WoodCost; resources.Ore -= item.OreCost; return(AddItem(token, userId, itemId)); }
public void TickEntityPhysics(EntityPos pos, EntityControls controls, float dt) { // This seems to make creatures clip into the terrain. Le sigh. // Since we currently only really need it for when the creature is dead, let's just use it only there // Also running animations for all nearby living entities is pretty CPU intensive so // the AnimationManager also just ticks if the entity is in view or dead if (!entity.Alive) { AdjustCollisionBoxToAnimation(); } foreach (EntityLocomotion locomotor in Locomotors) { if (locomotor.Applicable(entity, pos, controls)) { locomotor.Apply(dt, entity, pos, controls); } } EntityAgent agent = entity as EntityAgent; if (agent?.MountedOn != null) { pos.SetFrom(agent.MountedOn.MountPosition); pos.Motion.X = 0; pos.Motion.Y = 0; pos.Motion.Z = 0; return; } pos.Motion.X = GameMath.Clamp(pos.Motion.X, -10, 10); pos.Motion.Y = GameMath.Clamp(pos.Motion.Y, -10, 10); pos.Motion.Z = GameMath.Clamp(pos.Motion.Z, -10, 10); if (!controls.NoClip) { DisplaceWithBlockCollision(pos, controls, dt); } else { pos.X += pos.Motion.X; pos.Y += pos.Motion.Y; pos.Z += pos.Motion.Z; entity.Swimming = false; entity.FeetInLiquid = false; entity.OnGround = false; } // Shake the player violently when falling at high speeds /*if (movedy < -50) * { * pos.X += (rand.NextDouble() - 0.5) / 5 * (-movedy / 50f); * pos.Z += (rand.NextDouble() - 0.5) / 5 * (-movedy / 50f); * } */ //return result; }
public override void StartExecute() { base.StartExecute(); stopNow = false; siegeMode = false; bool giveUpWhenNoPath = targetPos.SquareDistanceTo(entity.Pos.XYZ) < 12 * 12; int searchDepth = 3500; // 1 in 20 times we do an expensive search if (world.Rand.NextDouble() < 0.05) { searchDepth = 10000; } if (!pathTraverser.NavigateTo(targetPos.Clone(), moveSpeed, MinDistanceToTarget(), OnGoalReached, OnStuck, giveUpWhenNoPath, searchDepth, true)) { // If we cannot find a path to the target, let's circle it! float angle = (float)Math.Atan2(entity.ServerPos.X - targetPos.X, entity.ServerPos.Z - targetPos.Z); double randAngle = angle + 0.5 + world.Rand.NextDouble() / 2; double distance = 4 + world.Rand.NextDouble() * 6; double dx = GameMath.Sin(randAngle) * distance; double dz = GameMath.Cos(randAngle) * distance; targetPos = targetPos.AddCopy(dx, 0, dz); int tries = 0; bool ok = false; BlockPos tmp = new BlockPos((int)targetPos.X, (int)targetPos.Y, (int)targetPos.Z); int dy = 0; while (tries < 5) { // Down ok? if (world.BlockAccessor.GetBlock(tmp.X, tmp.Y - dy, tmp.Z).SideSolid[BlockFacing.UP.Index] && !world.CollisionTester.IsColliding(world.BlockAccessor, entity.CollisionBox, new Vec3d(tmp.X + 0.5, tmp.Y - dy + 1, tmp.Z + 0.5), false)) { ok = true; targetPos.Y -= dy; targetPos.Y++; siegeMode = true; break; } // Down ok? if (world.BlockAccessor.GetBlock(tmp.X, tmp.Y + dy, tmp.Z).SideSolid[BlockFacing.UP.Index] && !world.CollisionTester.IsColliding(world.BlockAccessor, entity.CollisionBox, new Vec3d(tmp.X + 0.5, tmp.Y + dy + 1, tmp.Z + 0.5), false)) { ok = true; targetPos.Y += dy; targetPos.Y++; siegeMode = true; break; } tries++; dy++; } ok = ok && pathTraverser.NavigateTo(targetPos.Clone(), moveSpeed, MinDistanceToTarget(), OnGoalReached, OnStuck, giveUpWhenNoPath, searchDepth, true); stopNow = !ok; } currentFollowTime = 0; }
public override void InGuiIdle(IWorldAccessor world, ItemStack stack) { GuiTransform.Rotation.Y = GameMath.Mod(world.ElapsedMilliseconds / 50f, 360); }
public override bool ContinueExecute(float dt) { currentFollowTime += dt; lastPathUpdateSeconds += dt; if (!siegeMode && lastPathUpdateSeconds >= 1 && targetPos.SquareDistanceTo(targetEntity.ServerPos.X, targetEntity.ServerPos.Y, targetEntity.ServerPos.Z) >= 3 * 3) { pathTraverser.NavigateTo(targetPos.Clone(), moveSpeed, MinDistanceToTarget(), OnGoalReached, OnStuck, false, 2000, true); lastPathUpdateSeconds = 0; targetPos.Set(targetEntity.ServerPos.X, targetEntity.ServerPos.Y, targetEntity.ServerPos.Z); } if (jumpAnimOn && entity.World.ElapsedMilliseconds - finishedMs > 2000) { entity.AnimManager.StopAnimation(leapAnimationCode); } if (!siegeMode) { pathTraverser.CurrentTarget.X = targetEntity.ServerPos.X; pathTraverser.CurrentTarget.Y = targetEntity.ServerPos.Y; pathTraverser.CurrentTarget.Z = targetEntity.ServerPos.Z; } Cuboidd targetBox = targetEntity.CollisionBox.ToDouble().Translate(targetEntity.ServerPos.X, targetEntity.ServerPos.Y, targetEntity.ServerPos.Z); Vec3d pos = entity.ServerPos.XYZ.Add(0, entity.CollisionBox.Y2 / 2, 0).Ahead(entity.CollisionBox.XSize / 2, 0, entity.ServerPos.Yaw); double distance = targetBox.ShortestDistanceFrom(pos); bool inCreativeMode = (targetEntity as EntityPlayer)?.Player?.WorldData.CurrentGameMode == EnumGameMode.Creative; if (!inCreativeMode && leapAtTarget && rand.NextDouble() < leapChance) { bool recentlyJumped = entity.World.ElapsedMilliseconds - jumpedMS < 3000; if (distance > 0.5 && distance < 4 && !recentlyJumped && targetEntity.ServerPos.Y + 0.1 >= entity.ServerPos.Y) { double dx = (targetEntity.ServerPos.X + targetEntity.ServerPos.Motion.X * 80 - entity.ServerPos.X) / 30; double dz = (targetEntity.ServerPos.Z + targetEntity.ServerPos.Motion.Z * 80 - entity.ServerPos.Z) / 30; entity.ServerPos.Motion.Add( dx, leapHeightMul * GameMath.Max(0.13, (targetEntity.ServerPos.Y - entity.ServerPos.Y) / 30), dz ); float yaw = (float)Math.Atan2(dx, dz); entity.ServerPos.Yaw = yaw; jumpedMS = entity.World.ElapsedMilliseconds; finishedMs = entity.World.ElapsedMilliseconds; if (leapAnimationCode != null) { entity.AnimManager.StopAnimation("walk"); entity.AnimManager.StopAnimation("run"); entity.AnimManager.StartAnimation(new AnimationMetaData() { Animation = leapAnimationCode, Code = leapAnimationCode }.Init()); jumpAnimOn = true; } } if (recentlyJumped && !entity.Collided && distance < 0.5) { entity.ServerPos.Motion /= 2; } } float minDist = MinDistanceToTarget(); float range = lowTempMode ? belowTempSeekingRange : seekingRange; return (currentFollowTime < maxFollowTime && distance < range * range && (distance > minDist || targetEntity.ServerControls.TriesToMove) && targetEntity.Alive && !inCreativeMode && !stopNow ); }
/// <summary> /// Do the mob AI /// </summary> public override void Think() { GamePlayer playerowner = GetPlayerOwner(); long lastUpdate = 0; if (playerowner != null && !playerowner.Client.GameObjectUpdateArray.TryGetValue(new Tuple <ushort, ushort>(Body.CurrentRegionID, (ushort)Body.ObjectID), out lastUpdate)) { lastUpdate = 0; } // Load abilities on first Think cycle. if (!checkAbility) { CheckAbilities(); checkAbility = true; } if (playerowner != null && (GameTimer.GetTickCount() - lastUpdate) > ThinkInterval) { playerowner.Out.SendObjectUpdate(Body); } //See if the pet is too far away, if so release it! if (Owner is GamePlayer && IsMainPet && !GameMath.IsWithinRadius(Body, Owner, MAX_OWNER_FOLLOW_DIST)) { (Owner as GamePlayer).CommandNpcRelease(); } // if pet is in agressive mode then check aggressive spells and attacks first if (!Body.AttackState && AggressionState == eAggressionState.Aggressive) { CheckPlayerAggro(); CheckNPCAggro(); AttackMostWanted(); } // Check for buffs, heals, etc, interrupting melee if not being interrupted // Only prevent casting if we are ordering pet to come to us or go to target if (Owner is GameNPC || (Owner is GamePlayer && WalkState != eWalkState.ComeHere && WalkState != eWalkState.GoTarget)) { CheckSpells(eCheckSpellType.Defensive); } // Stop hunting player entering in steath if (Body.TargetObject != null && Body.TargetObject is GamePlayer) { GamePlayer player = Body.TargetObject as GamePlayer; if (Body.IsAttacking && player.IsStealthed && !previousIsStealthed) { Body.StopAttack(); Body.StopCurrentSpellcast(); RemoveFromAggroList(player); Body.TargetObject = null; FollowOwner(); } previousIsStealthed = player.IsStealthed; } // Always check offensive spells, or pets in melee will keep blindly melee attacking, // when they should be stopping to cast offensive spells. if (IsActive && m_aggressionState != eAggressionState.Passive) { CheckSpells(eCheckSpellType.Offensive); } if (!Body.AttackState && WalkState == eWalkState.Follow && Owner != null) { Follow(Owner); } }
void genPatches(int chunkX, int chunkZ) { int dx, dz, x, z; Block block; for (int i = 0; i < bpc.Patches.Length; i++) { BlockPatch blockPatch = bpc.Patches[i]; if (!blockPatch.PrePass) { continue; } float chance = blockPatch.Chance * bpc.ChanceMultiplier.nextFloat(); while (chance-- > rnd.NextDouble()) { dx = rnd.NextInt(chunksize); dz = rnd.NextInt(chunksize); x = dx + chunkX * chunksize; z = dz + chunkZ * chunksize; int y = heightmap[dz * chunksize + dx]; if (y <= 0 || y >= worldheight - 15) { continue; } tmpPos.Set(x, y, z); block = blockAccessor.GetBlock(tmpPos); // Place according to forest value int climate = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); if (bpc.IsPatchSuitableAt(blockPatch, block, api.WorldManager.MapSizeY, climate, y, 0, 0)) { int firstBlockId = 0; bool found = true; if (blockPatch.BlocksByRockType != null) { found = false; int dy = 1; while (dy < 5 && y - dy > 0) { string lastCodePart = blockAccessor.GetBlock(x, y - dy, z).LastCodePart(); if (RockBlockIdsByType.TryGetValue(lastCodePart, out firstBlockId)) { found = true; break; } dy++; } } if (found) { blockPatch.Generate(blockAccessor, rnd, x, y, z, firstBlockId); } } } } }
override internal void OnDeserialized() { base.OnDeserialized(); // Only one collision/selectionbox if (CollisionBoxR != null) { CollisionBoxes = ToCuboidf(CollisionBoxR); } if (SelectionBoxR != null) { SelectionBoxes = ToCuboidf(SelectionBoxR); } // Multiple collision/selectionboxes if (CollisionBoxesR != null) { CollisionBoxes = ToCuboidf(CollisionBoxesR); } if (SelectionBoxesR != null) { SelectionBoxes = ToCuboidf(SelectionBoxesR); } // Merged collision+selectioboxes if (CollisionSelectionBoxR != null) { CollisionBoxes = ToCuboidf(CollisionSelectionBoxR); SelectionBoxes = ToCuboidf(CollisionSelectionBoxR); } if (CollisionSelectionBoxesR != null) { CollisionBoxes = ToCuboidf(CollisionSelectionBoxesR); SelectionBoxes = ToCuboidf(CollisionSelectionBoxesR); } ResolveStringBoolDictFaces(SideSolidOpaqueAo); ResolveStringBoolDictFaces(SideSolid); ResolveStringBoolDictFaces(SideOpaque); ResolveStringBoolDictFaces(SideAo); ResolveStringBoolDictFaces(EmitSideAo); if (SideSolidOpaqueAo != null && SideSolidOpaqueAo.Count > 0) { ResolveDict(SideSolidOpaqueAo, ref SideSolid); ResolveDict(SideSolidOpaqueAo, ref SideOpaque); ResolveDict(SideSolidOpaqueAo, ref SideAo); ResolveDict(SideSolidOpaqueAo, ref EmitSideAo); } if (EmitSideAo == null) { EmitSideAo = new Dictionary <string, bool>() { { "all", LightAbsorption > 0 } }; ResolveStringBoolDictFaces(EmitSideAo); } if (LightHsv == null) { LightHsv = new byte[3]; } // Boundary check light values, if they go beyond allowed values the lighting system will crash LightHsv[0] = (byte)GameMath.Clamp(LightHsv[0], 0, ColorUtil.HueQuantities - 1); LightHsv[1] = (byte)GameMath.Clamp(LightHsv[1], 0, ColorUtil.SatQuantities - 1); LightHsv[2] = (byte)GameMath.Clamp(LightHsv[2], 0, ColorUtil.BrightQuantities - 1); }
public override bool OnHeldInteractStep(float secondsUsed, IItemSlot slot, IEntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel) { if (blockSel == null) { return(false); } if (slot.Itemstack.TempAttributes.GetInt("refilled") > 0) { return(false); } float prevsecondsused = slot.Itemstack.TempAttributes.GetFloat("secondsUsed"); slot.Itemstack.TempAttributes.SetFloat("secondsUsed", secondsUsed); float remainingwater = GetRemainingWateringSeconds(slot.Itemstack); SetRemainingWateringSeconds(slot.Itemstack, remainingwater -= secondsUsed - prevsecondsused); if (remainingwater <= 0) { return(false); } IWorldAccessor world = byEntity.World; BlockPos targetPos = blockSel.Position; Block facingBlock = world.BlockAccessor.GetBlock(blockSel.Position.AddCopy(blockSel.Face)); if (facingBlock.Code.Path == "fire") { world.BlockAccessor.SetBlock(0, blockSel.Position.AddCopy(blockSel.Face)); } Block block = world.BlockAccessor.GetBlock(blockSel.Position); bool notOnSolidblock = false; if ((block.CollisionBoxes == null || block.CollisionBoxes.Length == 0) && !block.IsLiquid()) { notOnSolidblock = true; targetPos = targetPos.DownCopy(); } BlockEntityFarmland be = world.BlockAccessor.GetBlockEntity(targetPos) as BlockEntityFarmland; if (be != null) { be.WaterFarmland(secondsUsed - prevsecondsused); } float speed = 4f; if (world.Side == EnumAppSide.Client) { ModelTransform tf = new ModelTransform(); tf.EnsureDefaultValues(); tf.Origin.Set(0.5f, 0.2f, 0.5f); tf.Translation.Set(-Math.Min(0.25f, speed * secondsUsed / 4), 0, 0); tf.Rotation.Z = GameMath.Min(60, secondsUsed * 90 * speed, 80 - remainingwater * 5); byEntity.Controls.UsingHeldItemTransformBefore = tf; } IPlayer byPlayer = null; if (byEntity is IEntityPlayer) { byPlayer = byEntity.World.PlayerByUid(((IEntityPlayer)byEntity).PlayerUID); } if (secondsUsed > 1 / speed) { Vec3d pos = blockSel.Position.ToVec3d().Add(blockSel.HitPosition); if (notOnSolidblock) { pos.Y = (int)pos.Y + 0.05; } WaterParticles.minPos = pos.Add(-0.125 / 2, 1 / 16f, -0.125 / 2); byEntity.World.SpawnParticles(WaterParticles, byPlayer); } return(true); }